Как я могу создать зеркальное отображение с зеркальной картой в пользовательском шейдере за три секунды?
Я создаю землю в WebGL с использованием Three.JS, и пока у меня есть земля с дневной и ночной текстурой и атмосферой. Теперь, чтобы закончить это, я хочу добавить зеркальное отражение к моей земле, которое будет отображаться только на водных участках. Теперь у меня уже есть зеркальная карта для этого, но я не могу озадачить все это вместе.
Я делаю все в пользовательском шейдере из-за земной / ночной / атмосферной штуковины, и я прочитал, что мне также нужно включить зеркальное вычисление в это уравнение, поскольку Three.JS не может составлять несколько шейдеров.
Это мой шейдер, и я застрял только в зеркальной части:
<script id="earthFragmentShader" type="x-shader/x-fragment">
uniform sampler2D dayTexture;
uniform sampler2D nightTexture;
uniform sampler2D specularTexture;
uniform vec3 sunDirection;
varying vec3 vNormal;
varying vec2 vUv;
void main() {
// Textures for day and night:
vec3 dayColor = texture2D( dayTexture, vUv ).xyz;
vec3 nightColor = texture2D( nightTexture, vUv ).xyz;
// compute cosine sun to normal so -1 is away from sun and +1 is toward sun.
float cosineAngleSunToNormal = dot(normalize(vNormal), sunDirection);
// sharpen the edge beween the transition
cosineAngleSunToNormal = clamp( cosineAngleSunToNormal * 3.0, -1.0, 1.0);
// convert to 0 to 1 for mixing
float mixAmount = cosineAngleSunToNormal * 0.5 + 0.5;
// Atmosphere:
float intensity = 1.09 - dot( vNormal, vec3( 0.0,0.0, 1.0 ) );
vec3 atmosphere = vec3( 1,1,1) * pow( intensity, 2.0 );
// Select day or night texture based on mixAmount.
vec3 color = mix( nightColor, dayColor + atmosphere, mixAmount );
// Specular:
vec3 specularAmount = texture2D( specularTexture, vUv ).xyz;
vec3 specularColor = vec3(1,1,1) * specularAmount;
color = mix(color, specularColor, mixAmount);
// Set the color
gl_FragColor = vec4(color, 1.0);
}
</script>
Пока что это просто добавляет зеркальную карту в качестве текстуры на земле, но, как я уже говорил, я хочу использовать это черно-белое изображение, чтобы показать какое-то зеркальное отражение. Кто-нибудь может указать мне правильное направление?
РЕДАКТИРОВАТЬ:
Хорошо, я добился целиком отображения с помощью следующего кода:
// Specular:
vec3 specularAmount = texture2D( specularTexture, vUv ).xyz;
vec3 specularColor = vec3(1,1,1);
float c = 0.35;
float p = 3.0;
float mixAmountSpecular = pow(c * dot(normalize(vNormal), sunDirection), p) * specularAmount.z;
// Select day or night texture based on mixAmount.
vec3 color = mix(dayColor, specularColor, mixAmountSpecular);
color = mix( nightColor, color + atmosphere, mixAmount );
Единственное, что осталось сейчас - как уменьшить зеркальное пятно... Есть мысли по этому поводу?
РЕДАКТИРОВАТЬ 2:
Хорошо, я наконец достиг этого, настроив некоторые параметры:
float c = 0.035;
float p = 30.0;
float mixAmountSpecular = pow(c * dot(normalize(vNormal), specularDirection), p) * (specularAmount.z * 0.5);
Для справки, мое sunDirection равно -2, 0,8, 1, а мое specularDirection равно -15, 10, 22,5.
1 ответ
Мои 2 правки подводят итог финального шейдера:
<script id="earthFragmentShader" type="x-shader/x-fragment">
uniform sampler2D dayTexture;
uniform sampler2D nightTexture;
uniform sampler2D specularTexture;
uniform vec3 sunDirection;
uniform vec3 specularDirection;
varying vec3 vNormal;
varying vec2 vUv;
void main() {
// Textures for day and night:
vec3 dayColor = texture2D( dayTexture, vUv ).xyz;
vec3 nightColor = texture2D( nightTexture, vUv ).xyz;
// compute cosine sun to normal so -1 is away from sun and +1 is toward sun.
float cosineAngleSunToNormal = dot(normalize(vNormal), sunDirection);
// sharpen the edge beween the transition
cosineAngleSunToNormal = clamp( cosineAngleSunToNormal * 3.0, -1.0, 1.0);
// convert to 0 to 1 for mixing
float mixAmount = cosineAngleSunToNormal * 0.5 + 0.5;
// Atmosphere:
float intensity = 1.09 - dot( vNormal, vec3( 0.0,0.0, 1.0 ) );
vec3 atmosphere = vec3( 1,1,1) * pow( intensity, 2.0 );
// Specular:
vec3 specularAmount = texture2D( specularTexture, vUv ).xyz;
vec3 specularColor = vec3(1,1,1);
// Play with these parameters to adjust the specular:
float c = 0.035; // Size, I guess...
float p = 30.0; // Blur
float mixAmountSpecular = pow(c * dot(normalize(vNormal), specularDirection), p) * (specularAmount.z * 0.5);
// Select day or night texture based on mixAmount.
vec3 color = mix(dayColor, specularColor, mixAmountSpecular);
color = mix( nightColor, color + atmosphere, mixAmount );
// Set the color
gl_FragColor = vec4(color, 1.0);
}
</script>