如何在实例的着色中增加光照

内容来源于 Stack Overflow,并遵循CC BY-SA 3.0许可协议进行翻译与使用

  • 回答 (2)
  • 关注 (0)
  • 查看 (166)

我如何添加照明(环境+定向)的着色器使用的InstancedBufferGe测?

这是我的顶点着色器:

precision highp float;
uniform mat4 modelViewMatrix;
uniform mat4 projectionMatrix;
uniform mat3 normalMatrix;
attribute vec3 position;
attribute vec3 offset;
attribute vec3 normal;
attribute vec2 uv;
attribute vec4 orientation;
varying vec2 vUv;

// lighting
struct DirectionalLight {
    vec3 direction;
    vec3 color;
    int shadow;
    float shadowBias;
    float shadowRadius;
    vec2 shadowMapSize;
    };
uniform DirectionalLight directionalLights[ NUM_DIR_LIGHTS ];
uniform vec3 ambientLightColor;
varying vec3 vLightFactor;
//

void main() {
    vec3 vPosition = position;
    vec3 vcV = cross(orientation.xyz, vPosition);
    vPosition = vcV * (2.0 * orientation.w) + (cross(orientation.xyz, vcV) * 2.0 + vPosition);
    vUv = uv;
    gl_Position = projectionMatrix * modelViewMatrix * vec4( offset + vPosition, 1.0 );

    // lighting
    vec4 ecPosition = modelViewMatrix*vec4(offset + vPosition,1.0);
    vec3 ecNormal= -(normalize(normalMatrix*normal));
    vec3 fromLight = normalize(directionalLights[0].direction);
    vec3 toLight = -fromLight;
    vec3 reflectLight = reflect(toLight,ecNormal);
    vec3 viewDir = normalize(-ecPosition.xyz);
    float ndots = dot(ecNormal, toLight);
    float vdotr = max(0.0,dot(viewDir,reflectLight));
    vec3 ambi = ambientLightColor;
    vec3 diff = directionalLights[0].color * ndots;
    vLightFactor = ambi + diff;     
    //

}

这是我的片段着色器:

precision highp float;
uniform sampler2D map;
varying vec2 vUv;

// lighting
varying vec3 vLightFactor;
//

void main() {
    gl_FragColor = texture2D(map, vUv) * vec4(vLightFactor,1.0);
}

这是我的材料:

var uniforms = Object.assign( 
    THREE.UniformsLib['lights'], 
    {
    map: { value: texture }
    }
);  

var material = new THREE.RawShaderMaterial({
    lights: true,
    uniforms: uniforms, 
    vertexShader: document.getElementById( 'vertexShader' ).textContent,
    fragmentShader: document.getElementById( 'fragmentShader' ).textContent,
});
提问于
用户回答回答于

在渲染中,场景的每个网格通常由模型矩阵、视图矩阵和投影矩阵进行转换。

模型矩阵定义了场景中网格的位置、方向和相对尺寸。模型矩阵将网格的顶点位置转换为世界空间。

视图矩阵描述观看场景的方向和位置。视图矩阵从沃尔德空间转换到视图(眼睛)空间。

注意,模型视图矩阵modelViewMatrix视图矩阵和模型矩阵的组合。但在您的例子中,模型矩阵可能是单位矩阵,以及modelViewMatrix可能等于视图矩阵。我假设,因为不是通过模型矩阵,而是通过向量进行模型转换orientationoffset(四元制)。

光可以在视野中或在世界空间中计算。

如果光是在视野空间中计算的话,那么光的位置和光的方向就必须从世界空间转换到视图空间。通常,这是在CPU上完成的(在每个帧之前),光参数制服是用视图空间坐标来设置的。由于视图位置在视图空间中是(0,0,0),是视图向量的归一化和逆顶点位置(在视图空间中)。

如果光是在世界空间中进行的,那么视图向量必须由视点位置(眼睛位置)和顶点位置(当然是在世界空间中)的差值来计算。

可以在视图空间中进行光的计算,因为光的方向和位置设置在视图空间中,你必须先把法线向量转换成世界空间,然后你必须从世界空间转换到观察空间。这必须与你对顶点位置的操作类似。将法向量添加到顶点位置。把这个位置转换成世界空间。世界空间中的法向量,是世界空间中计算出的位置与顶点位置的差值。

vec3 wNPosition = position + normal;
vec3 wNV        = cross(orientation.xyz, wNPosition);
wNPosition      = wNV * 2.0 * orientation.w + cross(orientation.xyz, wNV) * 2.0 + wNPosition;
vec3 wNormal    = normalize( wNPosition - vPosition );

在此假设下,您的着色代码可能如下所示:

vec3 wPosition       = position;
vec3 wV              = cross(orientation.xyz, wPosition);
wPosition            = offset + wV * 2.0 * orientation.w + cross(orientation.xyz, wV) * 2.0 + wPosition;
vec4 ecPosition      = modelViewMatrix * vec4(wPosition, 1.0);
vUv                  = uv;
gl_Position          = projectionMatrix * ecPosition;

// transform normal vector to world space
vec3 wNPosition      = position + normal;
vec3 wNV             = cross(orientation.xyz, wNPosition);
wNPosition           = offset + wNV * 2.0 * orientation.w + cross(orientation.xyz, wNV) * 2.0 + wNPosition;
vec3 ecNormal        = normalize(mat3(modelViewMatrix) * (wNPosition - wPosition));

// ambient light
vLightFactor         = ambientLightColor;

// diffuse light
vec3  ecToLight      = normalize(directionalLights[0].direction);
float NdotL          = max(0.0, dot(ecNormal, ecToLight));
vLightFactor        += NdotL * directionalLights[0].color; 

如果你想增加镜面光,你必须这样做:

// specular light
vec3  ecReflectLight = reflect( ecFromLight, ecNormal );
vec3  ecViewDir      = normalize(-ecPosition.xyz);
float VdotR          = max(0.0, dot(ecViewDir, ecReflectLight));
float kSpecular      = 4.0 * pow( VdotR, 0.3 * shininess ); // <--- set up shininess parameter
vLightFactor        += kSpecular * directionalLights[0].color;

顶点着色器:

precision highp float;

uniform mat4 modelViewMatrix;
uniform mat4 projectionMatrix;
uniform mat3 normalMatrix;

attribute vec3 position;
attribute vec3 offset;
attribute vec3 normal;
attribute vec2 uv;
attribute vec4 orientation;

varying vec2 vUv;
varying vec3 ecPosition;
varying vec3 ecNormal;

void main()
{
    vec3 wPosition   = position;
    vec3 wV          = cross(orientation.xyz, wPosition);
    pos              = offset + wV * 2.0 * orientation.w + cross(orientation.xyz, wV) * 2.0 + wPosition;
    vec4 vPos        = modelViewMatrix * vec4(wPosition, 1.0);
    ecPosition       = vPos.xyz;
    vUv              = uv;
    gl_Position      = projectionMatrix * vPos;

    // transform normal vector to world space
    vec3 wNPosition  = position + normal;
    vec3 wNV         = cross(orientation.xyz, wNPosition);
    wNPosition       = offset + wNV * 2.0 * orientation.w + cross(orientation.xyz, wNV) * 2.0 + wNPosition;
    ecNormal         = normalize(mat3(modelViewMatrix) * (wNPosition - wPosition));
}

碎片着色器:

precision highp float;

varying vec2 vUv;
varying vec3 ecPosition;
varying vec3 ecNormal;

uniform sampler2D map;
uniform mat4 modelViewMatrix;

struct DirectionalLight {
    vec3 direction;
    vec3 color;
    int shadow;
    float shadowBias;
    float shadowRadius;
    vec2 shadowMapSize;
};
uniform DirectionalLight directionalLights[ NUM_DIR_LIGHTS ];
uniform vec3 ambientLightColor;

void main()
{
    // ambient light
    float lightFactor = ambientLightColor;

    // diffuse light
    vec3  ecToLight      = normalize(directionalLights[0].direction);
    float NdotL          = max(0.0, dot(ecNormal, ecToLight));
    lightFactor         += NdotL * directionalLights[0].color; 

    // specular light
    vec3  ecReflectLight = reflect( ecFromLight, ecNormal );
    vec3  ecViewDir      = normalize(-ecPosition.xyz);
    float VdotR          = max(0.0, dot(ecViewDir, ecReflectLight));
    float kSpecular      = 4.0 * pow( VdotR, 0.3 * shininess ); // <--- set up shininess parameter
    lightFactor         += kSpecular * directionalLights[0].color;

    gl_FragColor = texture2D(map, vUv) * vec4(vec3(lightFactor), 1.0);
}
用户回答回答于

我的意思是,片段着色器应该是这样的:

precision highp float;

varying vec2 vUv;
varying vec3 ecPosition;
varying vec3 ecNormal;

uniform sampler2D map;
uniform mat4 modelViewMatrix;

struct DirectionalLight {
    vec3 direction;
    vec3 color;
    int shadow;
    float shadowBias;
    float shadowRadius;
    vec2 shadowMapSize;
};
uniform DirectionalLight directionalLights[ NUM_DIR_LIGHTS ];
uniform vec3 ambientLightColor;

void main()
{
    // ambient light
    vec3 lightFactor = ambientLightColor;

    // diffuse light
    vec3  ecFromLight    = normalize(directionalLights[0].direction);
    //vec3  ecToLight      = -ecFromLight;
    float NdotL          = max(0.0, dot(ecNormal, ecFromLight));
    lightFactor         += NdotL * directionalLights[0].color; 

    // specular light
    /*
    float shininess = 10.01;
    vec3  ecReflectLight = reflect( ecFromLight, ecNormal );
    vec3  ecViewDir      = normalize(-ecPosition.xyz);
    float VdotR          = max(0.0, dot(ecViewDir, ecReflectLight));
    float kSpecular      = 4.0 * pow( VdotR, 0.3 * shininess ); // <--- set up shininess parameter
    lightFactor         += kSpecular * directionalLights[0].color;
    */

    gl_FragColor = texture2D(map, vUv) * vec4(lightFactor, 1.0);
}

所属标签

可能回答问题的人

  • gulu丶咕噜

    0 粉丝1 提问5 回答
  • 华讯云

    0 粉丝0 提问4 回答
  • EatRice

    16 粉丝0 提问4 回答
  • 发条丶魔灵1

    9 粉丝526 提问3 回答

扫码关注云+社区

领取腾讯云代金券