2017-12-07 15 views
-2

私はPhongシェーディングを使って土地ベースのシーンに照明を照らそうとしています。私は現在Gouraudシェーディングを使用していますが、これは意図された球体の現実感をもたらしません。これに加えて、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

私が質問に答える場合は、代わりのAC、もう一度質問を削除します答えを黙らせるか? – Rabbid76

+0

一言で言えば、フォンシェーディングはサーフェスの法線を補間し、ピクセル単位で光を計算することです。あなたが見せてくれる作品はそうしているように見えますが、あなたが見せない作品はコメントするのが難しく、半分のコードをテストすることは全くできません。様々なシェーダーや独自のものを試してみたいと思ったらhttp://shadertoy.comは面白いかもしれないサイトです – tevemadar

+0

これは**ではありません** [グーローシェーディング](https:// en。 wikipedia.org/wiki/Gouraud_shading)では、頂点ごとにgauroudの光が計算され、フラグメントに対して補間されます。光は断片ごとに計算されるため、これは[Phong shading](https://en.wikipedia.org/wiki/Phong_shading)です。ライトモデルは[Blinn-Phongシェーディングモデル](https://www.wikipedia.org/wiki/Phong_reflection_model)と比較してsepcularハイライトが 'reflect'によって計算されるため、[Phong reflection model](https://en.wikipedia.org/wiki/Phong_reflection_model) //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; 
 
}

関連する問題