我正在尝试将置换贴图和镜面贴图都应用于地球,仅将置换贴图应用于月球。
我可以将高度贴图转换为法线贴图,但是如果我使用相同的高度贴图来应用置换贴图,它不会像我预期的那样工作。
以下是示例图像

正如你所看到的地球和月球周围的凹凸不平,但没有实际的高度差异。
如果我将镜面反射贴图应用到地球上,地球就会变成这样

我只想让地球的海洋发光,但我的代码把地球变成了一片漆黑,我只能看到地球上的一些白点……
这些纹理来自此site
下面是我的顶点着色器代码和片段着色器代码
"use strict";
const loc_aPosition = 3;
const loc_aNormal = 5;
const loc_aTexture = 7;
const VSHADER_SOURCE =
`#version 300 es
layout(location=${loc_aPosition}) in vec4 aPosition;
layout(location=${loc_aNormal}) in vec4 aNormal;
layout(location=${loc_aTexture}) in vec2 aTexCoord;
uniform mat4 uMvpMatrix;
uniform mat4 uModelMatrix; // Model matrix
uniform mat4 uNormalMatrix; // Transformation matrix of the normal
uniform sampler2D earth_disp;
uniform sampler2D moon_disp;
//uniform float earth_dispScale;
//uniform float moon_dispScale;
//uniform float earth_dispBias;
//uniform float moon_dispBias;
uniform bool uEarth;
uniform bool uMoon;
out vec2 vTexCoord;
out vec3 vNormal;
out vec3 vPosition;
void main()
{
float disp;
if(uEarth)
disp = texture(earth_disp, aTexCoord).r; //Extracting the color information from the image
else if(uMoon)
disp = texture(moon_disp, aTexCoord).r; //Extracting the color information from the image
vec4 displace = aPosition;
float displaceFactor = 2.0;
float displaceBias = 0.5;
if(uEarth || uMoon) //Using Displacement Mapping
{
displace += (displaceFactor * disp - displaceBias) * aNormal;
gl_Position = uMvpMatrix * displace;
}
else //Not using displacement mapping
gl_Position = uMvpMatrix * aPosition;
// Calculate the vertex position in the world coordinate
vPosition = vec3(uModelMatrix * aPosition);
vNormal = normalize(vec3(uNormalMatrix * aNormal));
vTexCoord = aTexCoord;
}`;
// Fragment shader program
const FSHADER_SOURCE =
`#version 300 es
precision mediump float;
uniform vec3 uLightColor; // Light color
uniform vec3 uLightPosition; // Position of the light source
uniform vec3 uAmbientLight; // Ambient light color
uniform sampler2D sun_color;
uniform sampler2D earth_color;
uniform sampler2D moon_color;
uniform sampler2D earth_bump;
uniform sampler2D moon_bump;
uniform sampler2D specularMap;
in vec3 vNormal;
in vec3 vPosition;
in vec2 vTexCoord;
out vec4 fColor;
uniform bool uIsSun;
uniform bool uIsEarth;
uniform bool uIsMoon;
vec2 dHdxy_fwd(sampler2D bumpMap, vec2 UV, float bumpScale)
{
vec2 dSTdx = dFdx( UV );
vec2 dSTdy = dFdy( UV );
float Hll = bumpScale * texture( bumpMap, UV ).x;
float dBx = bumpScale * texture( bumpMap, UV + dSTdx ).x - Hll;
float dBy = bumpScale * texture( bumpMap, UV + dSTdy ).x - Hll;
return vec2( dBx, dBy );
}
vec3 pertubNormalArb(vec3 surf_pos, vec3 surf_norm, vec2 dHdxy)
{
vec3 vSigmaX = vec3( dFdx( surf_pos.x ), dFdx( surf_pos.y ), dFdx( surf_pos.z ) );
vec3 vSigmaY = vec3( dFdy( surf_pos.x ), dFdy( surf_pos.y ), dFdy( surf_pos.z ) );
vec3 vN = surf_norm; // normalized
vec3 R1 = cross( vSigmaY, vN );
vec3 R2 = cross( vN, vSigmaX );
float fDet = dot( vSigmaX, R1 );
fDet *= ( float( gl_FrontFacing ) * 2.0 - 1.0 );
vec3 vGrad = sign( fDet ) * ( dHdxy.x * R1 + dHdxy.y * R2 );
return normalize( abs( fDet ) * surf_norm - vGrad );
}
void main()
{
vec2 dHdxy;
vec3 bumpNormal;
float bumpness = 1.0;
if(uIsSun)
fColor = texture(sun_color, vTexCoord);
else if(uIsEarth)
{
fColor = texture(earth_color, vTexCoord);
dHdxy = dHdxy_fwd(earth_bump, vTexCoord, bumpness);
}
else if(uIsMoon)
{
fColor = texture(moon_color, vTexCoord);
dHdxy = dHdxy_fwd(moon_bump, vTexCoord, bumpness);
}
// Normalize the normal because it is interpolated and not 1.0 in length any more
vec3 normal = normalize(vNormal);
// Calculate the light direction and make its length 1.
vec3 lightDirection = normalize(uLightPosition - vPosition);
// The dot product of the light direction and the orientation of a surface (the normal)
float nDotL;
if(uIsSun)
nDotL = 1.0;
else
nDotL = max(dot(lightDirection, normal), 0.0);
// Calculate the final color from diffuse reflection and ambient reflection
vec3 diffuse = uLightColor * fColor.rgb * nDotL;
vec3 ambient = uAmbientLight * fColor.rgb;
float specularFactor = texture(specularMap, vTexCoord).r; //Extracting the color information from the image
vec3 diffuseBump;
if(uIsEarth || uIsMoon)
{
bumpNormal = pertubNormalArb(vPosition, normal, dHdxy);
diffuseBump = min(diffuse + dot(bumpNormal, lightDirection), 1.1);
}
vec3 specular = vec3(0.0);
float shiness = 12.0;
vec3 lightSpecular = vec3(1.0);
if(uIsEarth && nDotL > 0.0)
{
vec3 v = normalize(-vPosition); // EyePosition
vec3 r = reflect(-lightDirection, bumpNormal); // Reflect from the surface
specular = lightSpecular * specularFactor * pow(dot(r, v), shiness);
}
//Update Final Color
if(uIsEarth)
fColor = vec4( (diffuse * diffuseBump * specular) + ambient, fColor.a); // Specular
else if(uIsMoon)
fColor = vec4( (diffuse * diffuseBump) + ambient, fColor.a);
else if(uIsSun)
fColor = vec4(diffuse + ambient, fColor.a);
}`;你能告诉我在哪里需要检查吗?
发布于 2019-12-16 13:43:08
如果是我,我会首先剥离着色器最简单的东西,看看我是否得到了我想要的东西。你想要一个镜面反射光芒,那么你的着色器中是否只有镜面反射计算的镜面反射光泽呢?
修剪着色器以仅绘制平面phong着色不会产生正确的结果
这一行
fColor = vec4( (diffuse * specular) + ambient, fColor.a);必须是
fColor = vec4( (diffuse + specular) + ambient, fColor.a);您可以将镜面反射相加,而不是乘以它。
"use strict";
const loc_aPosition = 3;
const loc_aNormal = 5;
const loc_aTexture = 7;
const VSHADER_SOURCE =
`#version 300 es
layout(location=${loc_aPosition}) in vec4 aPosition;
layout(location=${loc_aNormal}) in vec4 aNormal;
uniform mat4 uMvpMatrix;
uniform mat4 uModelMatrix; // Model matrix
uniform mat4 uNormalMatrix; // Transformation matrix of the normal
out vec3 vNormal;
out vec3 vPosition;
void main()
{
gl_Position = uMvpMatrix * aPosition;
// Calculate the vertex position in the world coordinate
vPosition = vec3(uModelMatrix * aPosition);
vNormal = normalize(vec3(uNormalMatrix * aNormal));
}`;
// Fragment shader program
const FSHADER_SOURCE =
`#version 300 es
precision highp float;
uniform vec3 uLightColor; // Light color
uniform vec3 uLightPosition; // Position of the light source
uniform vec3 uAmbientLight; // Ambient light color
in vec3 vNormal;
in vec3 vPosition;
out vec4 fColor;
void main()
{
vec2 dHdxy;
vec3 bumpNormal;
float bumpness = 1.0;
fColor = vec4(0.5, 0.5, 1, 1);
// Normalize the normal because it is interpolated and not 1.0 in length any more
vec3 normal = normalize(vNormal);
// Calculate the light direction and make its length 1.
vec3 lightDirection = normalize(uLightPosition - vPosition);
// The dot product of the light direction and the orientation of a surface (the normal)
float nDotL;
nDotL = max(dot(lightDirection, normal), 0.0);
// Calculate the final color from diffuse reflection and ambient reflection
vec3 diffuse = uLightColor * fColor.rgb * nDotL;
vec3 ambient = uAmbientLight * fColor.rgb;
float specularFactor = 1.0;
bumpNormal = normal;
vec3 specular = vec3(0.0);
float shiness = 12.0;
vec3 lightSpecular = vec3(1.0);
vec3 v = normalize(-vPosition); // EyePosition
vec3 r = reflect(-lightDirection, bumpNormal); // Reflect from the surface
specular = lightSpecular * specularFactor * pow(dot(r, v), shiness);
fColor = vec4( (diffuse + specular) + ambient, fColor.a); // Specular
}`;
function main() {
const m4 = twgl.m4;
const gl = document.querySelector('canvas').getContext('webgl2');
if (!gl) { return alert('need webgl2'); }
const prgInfo = twgl.createProgramInfo(gl, [VSHADER_SOURCE, FSHADER_SOURCE]);
const verts = twgl.primitives.createSphereVertices(1, 40, 40);
// calls gl.createBuffer, gl.bindBuffer, gl.bufferData for each array
const bufferInfo = twgl.createBufferInfoFromArrays(gl, {
aPosition: verts.position,
aNormal: verts.normal,
aTexCoord: verts.texcoord,
indices: verts.indices,
});
// calls gl.bindBuffer, gl.enableVertexAttribArray, gl.vertexAttribPointer for each attribute
twgl.setBuffersAndAttributes(gl, prgInfo, bufferInfo);
twgl.resizeCanvasToDisplaySize(gl.canvas);
gl.clearColor(0, 0, 0, 1);
gl.clear(gl.COLOR_BUFFER_BIT | gl.DEPTH_BUFFER_BIT);
gl.enable(gl.DEPTH_TEST);
gl.enable(gl.CULL_FACE);
gl.viewport(0, 0, gl.canvas.width, gl.canvas.height);
gl.useProgram(prgInfo.program);
const fov = 60 * Math.PI / 180;
const aspect = gl.canvas.clientWidth / gl.canvas.clientHeight;
const near = 0.1;
const far = 20.0;
const mat = m4.perspective(fov, aspect, near, far);
m4.translate(mat, [0, 0, -3], mat);
// calls gl.activeTexture, gl.bindTexture, gl.uniform
twgl.setUniforms(prgInfo, {
uMvpMatrix: mat,
uModelMatrix: m4.identity(), // Model matrix
uNormalMatrix: m4.identity(), // Transformation matrix of the normal
uLightColor: [1, 1, 1], // Light color
uLightPosition: [2, 2, 10], // Position of the light source
uAmbientLight: [0, 0, 0], // Ambient light color
});
// calls gl.drawArrays or gl.drawElements
twgl.drawBufferInfo(gl, bufferInfo);
}
main();body { margin: 0 }
canvas { display: block; width: 100vw; height: 100vh; }<script src="https://twgljs.org/dist/4.x/twgl-full.min.js"></script>
<canvas></canvas>
现在我们可以在镜面反射贴图中添加
"use strict";
const loc_aPosition = 3;
const loc_aNormal = 5;
const loc_aTexCoord = 7;
const VSHADER_SOURCE =
`#version 300 es
layout(location=${loc_aPosition}) in vec4 aPosition;
layout(location=${loc_aNormal}) in vec4 aNormal;
layout(location=${loc_aTexCoord}) in vec2 aTexCoord;
uniform mat4 uMvpMatrix;
uniform mat4 uModelMatrix; // Model matrix
uniform mat4 uNormalMatrix; // Transformation matrix of the normal
out vec3 vNormal;
out vec3 vPosition;
out vec2 vTexCoord;
void main()
{
gl_Position = uMvpMatrix * aPosition;
// Calculate the vertex position in the world coordinate
vPosition = vec3(uModelMatrix * aPosition);
vNormal = normalize(vec3(uNormalMatrix * aNormal));
vTexCoord = aTexCoord;
}`;
// Fragment shader program
const FSHADER_SOURCE =
`#version 300 es
precision highp float;
uniform vec3 uLightColor; // Light color
uniform vec3 uLightPosition; // Position of the light source
uniform vec3 uAmbientLight; // Ambient light color
uniform sampler2D specularMap;
in vec3 vNormal;
in vec3 vPosition;
in vec2 vTexCoord;
out vec4 fColor;
void main()
{
vec2 dHdxy;
vec3 bumpNormal;
float bumpness = 1.0;
fColor = vec4(0.5, 0.5, 1, 1);
// Normalize the normal because it is interpolated and not 1.0 in length any more
vec3 normal = normalize(vNormal);
// Calculate the light direction and make its length 1.
vec3 lightDirection = normalize(uLightPosition - vPosition);
// The dot product of the light direction and the orientation of a surface (the normal)
float nDotL;
nDotL = max(dot(lightDirection, normal), 0.0);
// Calculate the final color from diffuse reflection and ambient reflection
vec3 diffuse = uLightColor * fColor.rgb * nDotL;
vec3 ambient = uAmbientLight * fColor.rgb;
float specularFactor = texture(specularMap, vTexCoord).r; //Extracting the color information from the image
bumpNormal = normal;
vec3 specular = vec3(0.0);
float shiness = 12.0;
vec3 lightSpecular = vec3(1.0);
vec3 v = normalize(-vPosition); // EyePosition
vec3 r = reflect(-lightDirection, bumpNormal); // Reflect from the surface
specular = lightSpecular * specularFactor * pow(dot(r, v), shiness);
fColor = vec4( (diffuse + specular) + ambient, fColor.a); // Specular
}`;
function main() {
const m4 = twgl.m4;
const gl = document.querySelector('canvas').getContext('webgl2');
if (!gl) { return alert('need webgl2'); }
const prgInfo = twgl.createProgramInfo(gl, [VSHADER_SOURCE, FSHADER_SOURCE]);
const verts = twgl.primitives.createSphereVertices(1, 40, 40);
// calls gl.createBuffer, gl.bindBuffer, gl.bufferData for each array
const bufferInfo = twgl.createBufferInfoFromArrays(gl, {
aPosition: verts.position,
aNormal: verts.normal,
aTexCoord: verts.texcoord,
indices: verts.indices,
});
const specularTex = twgl.createTexture(gl, {src: 'https://i.imgur.com/JlIJu5V.jpg'});
function render(time) {
twgl.resizeCanvasToDisplaySize(gl.canvas);
gl.clearColor(0, 0, 0, 1);
gl.clear(gl.COLOR_BUFFER_BIT | gl.DEPTH_BUFFER_BIT);
gl.enable(gl.DEPTH_TEST);
gl.enable(gl.CULL_FACE);
gl.viewport(0, 0, gl.canvas.width, gl.canvas.height);
// calls gl.bindBuffer, gl.enableVertexAttribArray, gl.vertexAttribPointer for each attribute
twgl.setBuffersAndAttributes(gl, prgInfo, bufferInfo);
gl.useProgram(prgInfo.program);
const fov = 60 * Math.PI / 180;
const aspect = gl.canvas.clientWidth / gl.canvas.clientHeight;
const near = 0.1;
const far = 20.0;
const mat = m4.perspective(fov, aspect, near, far);
m4.translate(mat, [0, 0, -3], mat);
const model = m4.rotationY(time / 1000);
m4.multiply(mat, model, mat);
// calls gl.activeTexture, gl.bindTexture, gl.uniform
twgl.setUniforms(prgInfo, {
uMvpMatrix: mat,
uModelMatrix: model, // Model matrix
uNormalMatrix: model, // Transformation matrix of the normal
uLightColor: [1, 1, 1], // Light color
uLightPosition: [2, 2, 10], // Position of the light source
uAmbientLight: [0, 0, 0], // Ambient light color
specularMap: specularTex,
});
// calls gl.drawArrays or gl.drawElements
twgl.drawBufferInfo(gl, bufferInfo);
requestAnimationFrame(render);
}
requestAnimationFrame(render);
}
main();body { margin: 0 }
canvas { display: block; width: 100vw; height: 100vh; }<script src="https://twgljs.org/dist/4.x/twgl-full.min.js"></script>
<canvas></canvas>
那么你就不应该在你的着色器上使用太多的布尔条件。或者创建不同的着色器,以找到一种不使用布尔值的方法。举个例子,我们不需要
uniform sampler2D earth_disp;
uniform sampler2D moon_disp;
uniform sampler2D sun_color;
uniform sampler2D earth_color;
uniform sampler2D moon_color;
uniform sampler2D earth_bump;
uniform sampler2D moon_bump;
uniform bool uIsSun;
uniform bool uIsEarth;
uniform bool uIsMoon;我们可以只有
uniform sampler2D displacementMap;
uniform sampler2D surfaceColor;
uniform sampler2D bumpMap;然后我们可以将displacementMap和bumpMap设置为单个像素0,0,0,0纹理,并且将没有位移和凹凸。
至于太阳的不同照明,如果太阳既不使用凹凸贴图,也不使用置换贴图,甚至根本不使用照明,那么可以说使用不同的着色器会更好,但我们也可以像这样添加一个maxDot值
uniform float maxDot;
...
nDotL = max(dot(lightDirection, normal), maxDot)如果maxDot为零,我们将得到一个正常的点积。如果maxDot是一个,我们就不会得到照明。
"use strict";
const loc_aPosition = 3;
const loc_aNormal = 5;
const loc_aTexture = 7;
const VSHADER_SOURCE =
`#version 300 es
layout(location=${loc_aPosition}) in vec4 aPosition;
layout(location=${loc_aNormal}) in vec3 aNormal;
layout(location=${loc_aTexture}) in vec2 aTexCoord;
uniform mat4 uMvpMatrix;
uniform mat4 uModelMatrix; // Model matrix
uniform mat4 uNormalMatrix; // Transformation matrix of the normal
uniform sampler2D displacementMap;
out vec2 vTexCoord;
out vec3 vNormal;
out vec3 vPosition;
void main()
{
float disp;
disp = texture(displacementMap, aTexCoord).r;
vec4 displace = aPosition;
float displaceFactor = 0.1;
float displaceBias = 0.0;
displace.xyz += (displaceFactor * disp - displaceBias) * aNormal;
gl_Position = uMvpMatrix * displace;
// Calculate the vertex position in the world coordinate
vPosition = vec3(uModelMatrix * aPosition);
vNormal = normalize(mat3(uNormalMatrix) * aNormal);
vTexCoord = aTexCoord;
}`;
// Fragment shader program
const FSHADER_SOURCE =
`#version 300 es
precision highp float;
uniform vec3 uLightColor; // Light color
uniform vec3 uLightPosition; // Position of the light source
uniform vec3 uAmbientLight; // Ambient light color
uniform sampler2D surfaceColor;
uniform sampler2D bumpMap;
uniform sampler2D specularMap;
uniform float maxDot;
in vec3 vNormal;
in vec3 vPosition;
in vec2 vTexCoord;
out vec4 fColor;
vec2 dHdxy_fwd(sampler2D bumpMap, vec2 UV, float bumpScale)
{
vec2 dSTdx = dFdx( UV );
vec2 dSTdy = dFdy( UV );
float Hll = bumpScale * texture( bumpMap, UV ).x;
float dBx = bumpScale * texture( bumpMap, UV + dSTdx ).x - Hll;
float dBy = bumpScale * texture( bumpMap, UV + dSTdy ).x - Hll;
return vec2( dBx, dBy );
}
vec3 pertubNormalArb(vec3 surf_pos, vec3 surf_norm, vec2 dHdxy)
{
vec3 vSigmaX = vec3( dFdx( surf_pos.x ), dFdx( surf_pos.y ), dFdx( surf_pos.z ) );
vec3 vSigmaY = vec3( dFdy( surf_pos.x ), dFdy( surf_pos.y ), dFdy( surf_pos.z ) );
vec3 vN = surf_norm; // normalized
vec3 R1 = cross( vSigmaY, vN );
vec3 R2 = cross( vN, vSigmaX );
float fDet = dot( vSigmaX, R1 );
fDet *= ( float( gl_FrontFacing ) * 2.0 - 1.0 );
vec3 vGrad = sign( fDet ) * ( dHdxy.x * R1 + dHdxy.y * R2 );
return normalize( abs( fDet ) * surf_norm - vGrad );
}
void main()
{
vec2 dHdxy;
vec3 bumpNormal;
float bumpness = 1.0;
fColor = texture(surfaceColor, vTexCoord);
dHdxy = dHdxy_fwd(bumpMap, vTexCoord, bumpness);
// Normalize the normal because it is interpolated and not 1.0 in length any more
vec3 normal = normalize(vNormal);
// Calculate the light direction and make its length 1.
vec3 lightDirection = normalize(uLightPosition - vPosition);
// The dot product of the light direction and the orientation of a surface (the normal)
float nDotL;
nDotL = max(dot(lightDirection, normal), maxDot);
// Calculate the final color from diffuse reflection and ambient reflection
vec3 diffuse = uLightColor * fColor.rgb * nDotL;
vec3 ambient = uAmbientLight * fColor.rgb;
float specularFactor = texture(specularMap, vTexCoord).r; //Extracting the color information from the image
vec3 diffuseBump;
bumpNormal = pertubNormalArb(vPosition, normal, dHdxy);
diffuseBump = min(diffuse + dot(bumpNormal, lightDirection), 1.1);
vec3 specular = vec3(0.0);
float shiness = 12.0;
vec3 lightSpecular = vec3(1.0);
vec3 v = normalize(-vPosition); // EyePosition
vec3 r = reflect(-lightDirection, bumpNormal); // Reflect from the surface
specular = lightSpecular * specularFactor * pow(dot(r, v), shiness);
//Update Final Color
fColor = vec4( (diffuse * diffuseBump + specular) + ambient, fColor.a); // Specular
}`;
function main() {
const m4 = twgl.m4;
const gl = document.querySelector('canvas').getContext('webgl2');
if (!gl) { return alert('need webgl2'); }
const prgInfo = twgl.createProgramInfo(gl, [VSHADER_SOURCE, FSHADER_SOURCE]);
const verts = twgl.primitives.createSphereVertices(1, 40, 40);
// calls gl.createBuffer, gl.bindBuffer, gl.bufferData for each array
const bufferInfo = twgl.createBufferInfoFromArrays(gl, {
aPosition: verts.position,
aNormal: verts.normal,
aTexCoord: verts.texcoord,
indices: verts.indices,
});
const textures = twgl.createTextures(gl, {
zero: { src: new Uint8Array([0, 0, 0, 0])},
earthSpecular: { src: 'https://i.imgur.com/JlIJu5V.jpg' },
earthColor: { src: 'https://i.imgur.com/eCpD7bM.jpg' },
earthBump: { src: 'https://i.imgur.com/LzFNOP8.jpg' },
sunColor: { src: 'https://i.imgur.com/gl8zBLI.jpg', },
moonColor: { src: 'https://i.imgur.com/oLiU4fm.jpg', },
moonBump: { src: 'https://i.imgur.com/bDnjW8C.jpg', },
});
function render(time) {
// calls gl.bindBuffer, gl.enableVertexAttribArray, gl.vertexAttribPointer for each attribute
twgl.setBuffersAndAttributes(gl, prgInfo, bufferInfo);
twgl.resizeCanvasToDisplaySize(gl.canvas);
gl.enable(gl.DEPTH_TEST);
gl.enable(gl.CULL_FACE);
gl.viewport(0, 0, gl.canvas.width, gl.canvas.height);
gl.useProgram(prgInfo.program);
const aspect = gl.canvas.clientWidth / gl.canvas.clientHeight;
const fov = 60 * Math.PI / 180 / aspect;
const near = 0.1;
const far = 20.0;
const viewProjection = m4.perspective(fov, aspect, near, far);
m4.translate(viewProjection, [0, 0, -6], viewProjection);
draw([0, 0, 0], {
displacementMap: textures.earthBump,
bumpMap: textures.earthBump,
surfaceColor: textures.earthColor,
specularMap: textures.earthSpecular,
maxDot: 0,
uAmbientLight: [0, 0, 0],
});
draw([-2.2, 0, 0], {
displacementMap: textures.zero,
bumpMap: textures.zero,
surfaceColor: textures.sunColor,
specularMap: textures.zero,
maxDot: 1,
uAmbientLight: [0, 0, 0],
});
draw([2.2, 0, 0], {
displacementMap: textures.moonBump,
bumpMap: textures.moonBump,
surfaceColor: textures.moonColor,
specularMap: textures.zero,
maxDot: 0,
uAmbientLight: [0, 0, 0],
});
function draw(translation, uniforms) {
const model = m4.translation(translation);
m4.rotateY(model, time / 1000, model);
// calls gl.activeTexture, gl.bindTexture, gl.uniform
twgl.setUniforms(prgInfo, {
uMvpMatrix: m4.multiply(viewProjection, model),
uModelMatrix: model, // Model matrix
uNormalMatrix: m4.transpose(m4.inverse(model)), // Transformation matrix of the normal
uLightColor: [1, 1, 1], // Light color
uLightPosition: [2, 2, 10], // Position of the light source
uAmbientLight: [1, 0, 0], // Ambient light color
});
twgl.setUniforms(prgInfo, uniforms);
// calls gl.drawArrays or gl.drawElements
twgl.drawBufferInfo(gl, bufferInfo);
}
requestAnimationFrame(render);
}
requestAnimationFrame(render);
}
main();body { margin: 0 }
canvas { display: block; width: 100vw; height: 100vh; }<script src="https://twgljs.org/dist/4.x/twgl-full.min.js"></script>
<canvas></canvas>
至于置换,置换只在顶点上起作用,因此您需要球体中的许多顶点才能看到任何置换。
此外,还有一个与位移相关的bug。您将法线作为vec4传入,下面的代码行
displace += (displaceFactor * disp - displaceBias) * aNormal;最终添加vec4置换。换句话说,假设您从位于球体左侧的vec4(1,0,0,1)的a_Position开始。因为您将其声明为vec4,所以aNormal可能也是vec4(1,0,0,1)。假设你实际上是通过缓冲区中的属性传递vec3正常数据,W的默认值是1。假设disp是1,displaceFactor是2,displaceBias是0.5,这就是你所拥有的。你最终会得到
displace = vec4(1,0,0,1) + (2 * 1 + 0.5) * vec4(1,0,0,1)
displace = vec4(1,0,0,1) + (1.5) * vec4(1,0,0,1)
displace = vec4(1,0,0,1) + vec4(1.5,0,0,1.5)
displace = vec4(2.5,0,0,2.5)但您不希望W为2.5。一种修复方法是只使用normal的xyz部分。
displace.xyz += (displaceFactor * disp - displaceBias) * aNormal.xyz;更正常的修复方法是只将normal属性声明为vec3
in vec3 aNormal;
displace.xyz += (displaceFactor * disp - displaceBias) * aNormal;在我上面的例子中,球体的半径仅为1,所以我们只需要稍微调整一下这个位移。我将displaceFactor设置为0.1,将displaceBias设置为0。
https://stackoverflow.com/questions/59349723
复制相似问题