2015-10-13 2 views
2

Я пишу пользовательский ShaderMaterial и решил включить свет и туман. Пока что так хорошо, и у меня есть шейдер, интегрированный с тремя. Js строят его туман, окружающий и точечный свет (он служит моей цели).three.js ShaderMaterial FlatShading

Тем не менее, затенение я получаю его гладким, а не плоским. Прежде чем вы, ребята, решите предложить добавить в ShaderMaterial флаг shading: THREE.FlatShading, помните, что это настраиваемый шейдер, и поэтому это ничего не сделает.

Поскольку FlatShading выполняется путем вычисления центроида треугольника и заполнения всех цветов на основе этого вектора, я думал, что использование нормалей треугольников будет делать трюк .. очевидно, что это действительно ... Это правильный способ есть свет FlatShading, где все пиксели внутри треугольника имеют один единственный цвет? Если да, то что мне не хватает?

вот мой шейдер в CoffeeScript

класс SomeShader

constructor: -> 

    @defines = {} 

    @uniforms = THREE.UniformsUtils.merge [ 
     THREE.UniformsLib['fog'] 
     THREE.UniformsLib['lights'] 
     { 
      color: { type: 'c', value: new THREE.Color(0xffffff) } 
     } 
    ] 

    @vertex = [ 
     'uniform vec3 ambientLightColor;' 
     '#if MAX_POINT_LIGHTS > 0' 
     ' uniform vec3 pointLightColor[MAX_POINT_LIGHTS];' 
     ' uniform vec3 pointLightPosition[MAX_POINT_LIGHTS];' 
     ' uniform float pointLightDistance[MAX_POINT_LIGHTS];' 
     '#endif' 

     'uniform vec3 color;' 
     'varying vec4 v_color;' 

     'void main() {' 
     # lights 
     ' vec3 norm = normalMatrix * normal;' 
     ' vec3 pos = (modelViewMatrix * vec4(position-norm, 1.0)).xyz;' 
     ' vec3 outgoingLight = vec3(1.);' 
     ' vec4 addedLights = vec4(0., 0., 0., 1.);' 
     ' #if MAX_POINT_LIGHTS > 0' 
     ' for(int l = 0; l < MAX_POINT_LIGHTS; l++) {' 
     '  vec3 lightDirection = normalize(pos - pointLightPosition[l]);' 
     '  addedLights.rgb += clamp(dot(-lightDirection, norm), 0.0, 1.0) * pointLightColor[l];' 
     ' }' 
     ' #endif' 
     ' addedLights += vec4(ambientLightColor, 1.);' 
     ' v_color = vec4(outgoingLight, 1.) * addedLights;' 
     ' gl_Position = projectionMatrix * modelViewMatrix * vec4(newPosition, 1.0);' 
     '}' 
    ].join '\n' 

    @fragment = [ 
     THREE.ShaderChunk['fog_pars_fragment'] 

     'varying vec4 v_color;' 

     'void main() {' 
     ' vec3 outgoingLight = vec3(1.);' 
      THREE.ShaderChunk['fog_fragment'] 
     ' gl_FragColor = v_color * vec4(outgoingLight, 1.);' 
     '}' 
    ].join '\n' 
+1

что плохого при использовании только вычислитьFaceNormals()? – pailhead

+0

Я попытался называть '' 'geometry.computeFaceNormals()' '', но ничего не делает ... – andrevenancio

+0

Я не уверен, что это правильная последовательность, но вы можете попробовать применить flatshading, потому что это может повлиять на нормальный атрибут заполняется нормалями лица или нормалями вершин. Помните, что независимо от того, что это пользовательский шейдер, вы все еще используете предопределенный атрибут (положение, uv, цвет, нормальный ...) – pailhead

ответ

3

Вы используете ShaderMaterial и ваши вытесняют свои вершины в вершинном шейдере с функцией шума. Вы также хотите перепроверить нормали вершин, чтобы затенение было плоским, т. Е. Гранено.

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

Таким образом, в вашем вершинном шейдере, вычислить следующие varying:

varying vec3 vViewPosition; 

vec4 mvPosition = modelViewMatrix * vec4(displacedPosition, 1.0); 
vViewPosition = - mvPosition.xyz; // vector from vertex to camera 

Затем в пиксельном шейдер, вычислить нормальные, используя производные экранного пространства:

normal = normalize(cross(dFdx(vViewPosition), dFdy(vViewPosition))); 

Теперь, используя ваш модели освещения для вычисления затенения в шейдере фрагмента.

3 .js r.73

+0

спасибо за ваш ответ.Это было очень полезно, и я сделал некоторый прогресс. Однако, как вы можете видеть из моего [jsfiddle] (http://jsfiddle.net/andrevenancio/hr67e6kv/), что-то не так с световой позицией ... Любая идея? @WestLangley? – andrevenancio

+0

на самом деле просто исправил ее. Спасибо за всю помощь :) – andrevenancio