【问题标题】:WebGL basic shader confusionWebGL 基本着色器混淆
【发布时间】:2015-09-15 19:47:41
【问题描述】:

我正在学习 WebGL 着色器,但它们把我搞糊涂了。这是我到目前为止得到的:

<script type="x-shader/x-vertex" id="vertexshader">

    #ifdef GL_ES
        precision highp float;
    #endif

    void main()
    {
        gl_Position = projectionMatrix * modelViewMatrix * vec4( position, 1.0 );
    }

</script>

<script type="x-shader/x-fragment" id="fragmentshader">

    #ifdef GL_ES
        precision highp float;
    #endif

    void main()
    {
        gl_FragColor    = vec4(1.0, 0.0, 1.0, 1.0);
    }

</script>

到目前为止一切顺利,它可以编译,我得到一个粉红色的立方体。

现在混乱设置了它。据我了解,片段着色器用于修改颜色,顶点着色器用于修改形状。

我不明白 gl_FragColor 是设置整个对象的颜色还是以某种顺序绘制的,我可以在其中操纵着色器中的坐标以使其随机着色?

如果是这样,它如何知道什么形状和着色顺序?

另外,如果我只想使用fragmentsshader,为什么还需要定义vertexshader?默认的gl_Position行是做什么的,为什么需要它?

到目前为止我尝试过的所有 GLSL 教程,代码都无法正常工作,并且 three.js 无法编译它。有什么建议从哪里开始?

【问题讨论】:

  • 我不是专家,所以我什至不会解释我所知道的一点点,但my experiments 可能会对你有所帮助。
  • 另外,youtube 上的This playlist 对我帮助很大
  • @2pha,非常感谢,您的实验很容易理解!
  • 你读过哪些教程? Do these help?
  • 真甜蜜系列gman!

标签: javascript opengl-es three.js webgl


【解决方案1】:

这个问题非常广泛。

假设你做了这样的事情:

var myRenderer = new THREE.WebGLRenderer();
var myScene = new THREE.Scene();
var myTexture = new THREE.Texture();
var myColor = new THREE.Color();
var myMaterial = new THREE.MeshBasicMaterial({color:myColor, map:myTexture});
var myColoredAndTexturedCube = new THREE.Mesh( new THREE.CubeGeometry(), myMaterial); 
var myCamera = new THREE.Camera();

如果您连接所有这些,您将在屏幕上渲染一个立方体,如果您提供颜色和纹理,它将显示两者(由颜色着色的纹理)。

虽然在幕后发生了很多事情。 Three.js 将通过 WebGL API 向 gpu 发出指令。这些是非常低级的调用,例如“获取这块内存并准备好绘制它”“准备这个着色器来处理这块内存”“为这个调用设置混合模式”。

我不明白 gl_FragColor 是设置整个对象的颜色,还是按某种顺序绘制的,我可以在其中操纵着色器中的坐标以便它随机着色?

如果是,它怎么知道什么形状和着色顺序?

你应该阅读一些关于渲染管道的知识,也许你一开始不会理解它,但它肯定可以澄清一些事情。

gl_FragColor 设置缓冲区中像素的颜色(可以是您的屏幕,也可以是屏幕外纹理)。是的,它为“整个对象”设置颜色,但整个对象可以是粒子云(您可以将其解释为多个对象)。您可以拥有一个由 10x10 立方体组成的网格,每个立方体的颜色不同,但仍使用一次绘制调用(一个对象)进行渲染。

所以回到你的shder:

//you dont see this, but three injects this for you, try intentionally adding a mistake to your shader, when your debugger complains, youll see the entire shader and these lines in it

uniform mat4 projectionMatrix; //one mat4 shared across all vertices/pixels
uniform mat4 modelViewMatrix; //one mat4 shared across all vertices/pixels
attribute vec3 position;  //actual vertex, this value is different in each vertex


//try adding this
varying vec2 vUv;

void main()
{

    vUv = uv;  //uv, just like position, is another attribute that gets created for you automatically, this way we are sending it to the pixel shader through the varying vec2 vUv.


    //this is the transformation 
    //projection matrix is what transforms space into perspective (vanishing points, things get smaller as they get further away from the camera)
    //modelViewMatrix are actually two matrices, viewMatrix, which is also part of the camera (how is this camera rotated and moved compared to the rest of the world)
    //finally the modelMatrix - how big is the object, where it stands, and how it's rotated

    gl_Position = projectionMatrix * modelViewMatrix * vec4( position, 1.0 );
    gl_Position = projectionMatrix * viewMatrix * modelMatrix * vec4( position , 1.0 ); //will do the same thing
}

你用三个制作的每个材质都有这部分着色器。例如,这不足以进行光照,因为它没有法线。

试试这个片段着色器:

varying vec2 vUv; //coming in from the vertex shader

void main(){
    gl_FragColor = vec4( vUv , 0.0 , 1.0);
}

或者更好的是,让我们用颜色显示物体的世界位置:

顶点着色器:

varying vec3 vertexWorldPosition; 

void main(){
    
    vec4 worldPosition = modelMatrix * vec4( position , 1.0 ); //compute the world position, remember it, 
    //model matrix is mat4 that transforms the object from object space to world space, vec4( vec3 , 1.0 ) creates a point rather than a direction in "homogeneous coordinates"

    //since we only need this to be vec4 for transformations and working with mat4, we save the vec3 portion of it to the varying variable
    vertexWorldPosition = worldPosition.xyz; // we don't need .w

    //do the rest of the transformation - what is this world space seen from the camera's point of view,
    gl_Position = viewMatrix * worldPosition;
    
    //we used gl_Position to write the previous result, we could have used a new vec4 cameraSpace (or eyeSpace, or viewSpace) but we can also write to gl_Position

    gl_Position = projectionMatrix * gl_Position; //apply perspective distortion
}

片段着色器:

varying vec3 vertexWorldPosition; //this comes in from the vertex shader
void main(){
    gl_FragColor = vec4( vertexWorldPosition , 1.0 );
}

如果您在 0,0,0 处创建一个球体并且不移动它,那么一半将是黑色的,另一半将是彩色的。根据规模,它可能是白色的。假设半径为 100,您将看到从 0 到 1 的渐变,其余部分将是白色(或 r、g、b,固定为 1.0)。然后尝试这样的事情

 gl_FragColor = vec4( vec3( sin( vertexWorldPosition.x ) ), 1.0 );

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2016-04-06
    • 1970-01-01
    • 2017-07-03
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2014-03-24
    相关资源
    最近更新 更多