2015-06-29 2 views
0

Я изучаю шейдеры WebGL, но они путают мне живой ад. Это то, что я получил до сих пор:WebGL basic shader confusion

<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 задает цвет для всего объекта или нарисован в каком-то порядке, где я могу манипулировать кординатами в шейдере, чтобы он стал цветным случайным образом, например?

Если да, то как он узнает, какую форму и порядок окраски?

Кроме того, почему мне нужно определить vertexshader, если я хочу использовать только fragmentshader и что делает линия gl_Position по умолчанию и зачем она нужна?

Все обучающие материалы GLSL, которые я пробовал до сих пор, код никогда не работает, а three.js не скомпилирует его. Любые предложения, с чего начать?

+1

Я не эксперт, так что я обыкновение даже пытаться объяснить то немногое, что я знаю, но [мои эксперименты] (http://blog.2pha.com/experimenting-threejs-shaders и-shadermaterial) могут помочь вам. – 2pha

+1

Кроме того, [Этот плейлист] (https://www.youtube.com/playlist?list=PLW3Zl3wyJwWMpFSRpeMmSBGDShbkiV1Cq) на youtube мне очень помог – 2pha

+0

@ 2pha, большое спасибо, ваши эксперименты легко следовать! – user3578847

ответ

2

Этот вопрос довольно широк.

Допустим, вы делаете что-то вроде этого:

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 выдает инструкции для gpu через API WebGL. Это очень низкие вызовы, такие как «взять этот кусок памяти и подготовить его для рисования», «подготовить этот шейдер для обработки этого блока памяти», чтобы установить режим смешивания для этого вызова ».

Я не понимаю, делает gl_FragColor устанавливает цвет для всего объекта или его рисуется в какой-то порядок, где я мог манипулировать cordinates в затенении, так что он получает цветные randomply, например?

Если да, то как он узнает, какую форму и порядок окраски?

Вы должны немного прочитать о конвейере рендеринга, возможно, вы сначала не поймете все это, но это может определенно прояснить некоторые вещи.

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); 
Смежные вопросы