2017-12-07 29 views
-2

퐁 쉐이딩을 사용하여 어스 기반 장면에 조명을 비춰려고합니다. 나는 현재 구라 우드 쉐이딩을 사용하고 있는데, 이것은 구의 리얼리즘을 의도 한 바대로 가져 오지 않습니다. 이 외에도 here처럼 꼭지점에서 일어나는 하이라이트가 표시됩니다.WebGL에서 Phong Shader를 어떻게 사용합니까?

다음은 내 장면과 관련된 코드입니다.

조명 계산;

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

 
attribute vec3 aVertexPosition; 
 
attribute vec3 aVertexNormal; 
 
attribute vec2 aTextureCoordinates; 
 

 
uniform mat4 uMVMatrix; 
 
uniform mat4 uPMatrix; 
 
uniform mat3 uNMatrix; 
 

 
varying vec2 vTextureCoordinates; 
 
varying vec3 vNormalEye; 
 
varying vec4 vPosition; 
 

 
void main() { 
 
    vNormalEye = normalize(uNMatrix * aVertexNormal); 
 

 
    vPosition = uMVMatrix * vec4(aVertexPosition,1.0); 
 
    gl_Position = uPMatrix * uMVMatrix * vec4(aVertexPosition,1.0); 
 
    vTextureCoordinates = aTextureCoordinates; 
 
} 
 

 
</script> 
 

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

 
precision mediump float; 
 

 
varying vec2 vTextureCoordinates; 
 
varying vec3 vNormalEye; 
 
varying vec4 vPosition; 
 

 
uniform sampler2D uSampler; 
 

 
uniform vec3 uAmbientLightColor; 
 
uniform vec3 uLightPosition; 
 
uniform vec3 uDiffuseLightColor; 
 
uniform vec3 uSpecularLightColor; 
 

 
const float shine = 32.0; 
 

 
void main() { 
 

 
    vec3 direction = normalize(-vPosition.xyz + uLightPosition); 
 
    vec3 reflection = reflect(-direction,vNormalEye); 
 

 
    float rdotv = max(dot(reflection,direction),0.0); 
 
    float specularLightWeighting = pow(rdotv,shine); 
 

 
    float directionalLightWeighting = max(dot(vNormalEye,uLightPosition),0.0); 
 
    vec3 vLightWeighting = uAmbientLightColor + uDiffuseLightColor * directionalLightWeighting + uSpecularLightColor * specularLightWeighting; 
 

 
    vec4 textureColor = texture2D(uSampler,vec2(vTextureCoordinates.s,vTextureCoordinates.t)); 
 
    gl_FragColor = vec4(textureColor.rgb * vLightWeighting, textureColor.a); 
 
} 
 
</script>

조명 설정;

function setupLights() { 
 

 
    var angleDegree = 60; 
 
    var lightDistance = 3.5;//Light intensity 
 
    var angleRadian = angleDegree * Math.PI/180; //Work out 60 degrees from180 degress 
 
    var xDir = Math.cos(angleRadian); 
 
    var yDir = Math.sin(angleRadian); 
 

 
    gl.uniform3fv(pwgl.uniformLightPositionLoc, [lightDistance * xDir, lightDistance * yDir, 0.0]); 
 
    gl.uniform3fv(pwgl.uniformAmbientLightColorLoc, [0.4, 0.4, 0.4]); 
 
    gl.uniform3fv(pwgl.uniformDiffuseLightColorLoc, [0.7, 0.7, 0.7]); 
 
    gl.uniform3fv(pwgl.uniformSpecularLightColorLoc, [0.8, 0.8, 0.8]); 
 
}

이것에 대해 이동이 가장 좋은 방법은 무엇입니까 ? 어떤 종류의 조명 계산을 구현해야합니까?

또한 구형의 사실성에 가장 적합한 음영 유형은 무엇입니까?

+0

내가 질문에 대답하는 경우, 대신 교류의 다시 질문을 삭제합니다 대답을 듣고 있니? – Rabbid76

+0

퐁 쉐이딩은 표면 법선을 보간하고 픽셀 단위로 빛을 계산하는 것입니다. 당신이 보여준 조각들은 그렇게하는 것처럼 보이고, 보여주지 않는 조각들은 논평하기 어렵고, 하프 코드를 시험하는 것은 전혀 불가능합니다. 다양한 쉐이더를보고 싶거나 자체 실험을하고 싶다면 http://shadertoy.com은 재미있는 사이트 – tevemadar

+0

을 찾을 수 있습니다 ** This is not ** [Gouraud shading] (https : // en. wikipedia.org/wiki/Gouraud_shading)에서 gauroud light는 be 頂点 당 계산되고 조각에 대해 보간됩니다. 빛은 조각마다 계산되므로 [Phong shading] (https://en.wikipedia.org/wiki/Phong_shading)입니다. Light 모델은 [Phinn reflection model] (https://en.wikipedia.org/wiki/Phong_reflection_model)입니다. 왜냐하면 [Blinn-Phong 쉐이딩 모델] (https : //en.wikipedia.org/wiki/Blinn%E2%80%93Phong_shading_model) 여기서 반쪽 방향 벡터가 사용됩니다. – Rabbid76

답변

0

조각 쉐이더

void main() { 
 

 
// Calculate the vector (L) to the light source 
 
vec3 vectorToLightSource = normalize(uLightPosition - vPositionEye3); 
 
// Calculate N dot L for diffuse lighting 
 
float diffuseLightWeighting = max(dot(vNormalEye, 
 
     vectorToLightSource), 0.0); 
 
// Calculate the reflection vector (R) that is needed for specular light 
 
vec3 reflectionVector = normalize(reflect(
 
     -vectorToLightSource, vNormalEye)); 
 
// Calculate viewVector (v) in eye coordinates as 
 
// (0.0, 0.0, 0.0) - vPositionEye3 
 
vec3 viewVectorEye = -normalize(vPositionEye3); 
 
float rdotv = max(dot(reflectionVector, viewVectorEye), 0.0); 
 
float specularLightWeighting = pow(rdotv, shininess); 
 

 
// Sum up all three reflection components 
 
vec3 lightWeighting = 
 
\t \t \t uAmbientLightColor + 
 
\t \t \t uDiffuseLightColor * diffuseLightWeighting + 
 
\t \t \t uSpecularLightColor * specularLightWeighting; 
 

 
// Sample the texture 
 
vec4 texelColor = texture2D(uSampler, vTextureCoordinates); 
 
// modulate texel color with lightweigthing and write as final color 
 
gl_FragColor = vec4(lightWeighting.rgb * texelColor.rgb, 
 
\t \t \t \t texelColor.a); 
 
}

버텍스 쉐이더

void main() { 
 
// Get vertex position in eye coordinates and send to the fragment shader 
 
vec4 vertexPositionEye4 = uMVMatrix * vec4(aVertexPosition, 
 
\t \t \t \t \t 1.0); 
 
vPositionEye3 = vertexPositionEye4.xyz/
 
\t \t \t \t \t vertexPositionEye4.w; 
 
// Transform the normal to eye coordinates and send to fragment shader 
 
vNormalEye = normalize(uNMatrix * aVertexNormal); 
 

 
// Transform the geometry 
 
gl_Position = uPMatrix * uMVMatrix * vec4(aVertexPosition, 
 
\t \t \t \t \t 1.0); 
 
vTextureCoordinates = aTextureCoordinates; 
 
}