【发布时间】:2014-07-23 11:24:10
【问题描述】:
我正在努力学习如何制作着色器,不久前,我在这里发布了一个问题:GLSL Shader - Shadow between 2 textures on a plane
所以,答案给了我正确的方向,但是我在检查当前片段和灯光位置之间是否存在不透明的片段时遇到了一些麻烦。
所以这里是代码:
顶点着色器:
attribute vec3 position;
attribute vec3 normal;
attribute vec2 uv;
varying vec2 uvVarying;
varying vec3 normalVarying;
varying vec3 posVarying;
uniform vec4 uvBounds0;
uniform mat4 agk_World;
uniform mat4 agk_ViewProj;
uniform mat3 agk_WorldNormal;
void main()
{
vec4 pos = agk_World * vec4(position,1);
gl_Position = agk_ViewProj * pos;
vec3 norm = agk_WorldNormal * normal;
posVarying = pos.xyz;
normalVarying = norm;
uvVarying = uv * uvBounds0.xy + uvBounds0.zw;
}
还有片段着色器:
#ifdef GL_ES
#ifdef GL_FRAGMENT_PRECISION_HIGH
precision highp float;
#else
precision mediump float;
#endif
#endif
uniform sampler2D texture0;
uniform sampler2D texture1;
varying vec2 uvVarying;
varying vec3 normalVarying;
varying vec3 posVarying;
uniform vec4 uvBounds0;
uniform vec2 playerPos;
uniform vec2 agk_resolution;
uniform vec4 agk_PLightPos;
uniform vec4 agk_PLightColor;
uniform vec4 agk_ObjColor;
void main (void)
{
vec4 lightPos = agk_PLightPos;
lightPos.x = playerPos.x;
lightPos.y = -playerPos.y;
vec3 dir = vec3(lightPos.x - posVarying.x, lightPos.y - posVarying.y, lightPos.z - posVarying.z);
vec3 norm = normalize(normalVarying);
float atten = dot(dir,dir);
atten = clamp(lightPos.w/atten,0.0,1.0);
float intensity = dot(normalize(dir),norm);
intensity = clamp(intensity,0.0,1.0);
vec3 lightColor = agk_PLightColor.rgb * intensity * atten;
vec3 shadowColor = agk_PLightColor.rgb * 0;
bool inTheShadow = false;
if (intensity * atten > 0.05) {
float distanceToLight = length(posVarying.xy - lightPos.xy);
for (float i = distanceToLight; i > 0.0; i -= 0.1) {
vec2 uvShadow = ???
if (texture2D(texture0, uvShadow).a > 0) {
inTheShadow = true;
break;
}
}
}
if (texture2D(texture0, uvVarying).a == 0) {
if (inTheShadow == true) {
gl_FragColor = texture2D(texture1, uvVarying) * vec4(shadowColor, 1) * agk_ObjColor;
}
else {
gl_FragColor = texture2D(texture1, uvVarying) * vec4(lightColor, 1) * agk_ObjColor;
}
}
else {
gl_FragColor = texture2D(texture0, uvVarying) * agk_ObjColor;
}
}
所以,这是我遇到一些麻烦的部分:
bool inTheShadow = false;
if (intensity * atten > 0.05) {
float distanceToLight = length(posVarying.xy - lightPos.xy);
for (float i = distanceToLight; i > 0.0; i -= 0.1) {
vec2 uvShadow = ???
if (texture2D(texture0, uvShadow).a > 0) {
inTheShadow = true;
break;
}
}
}
我首先检查我是否在强度 * atten > 0.05 的光半径内
然后我得到当前片段到灯光位置的距离。
然后,我创建了一个 for 循环,检查当前片段和灯光位置之间的每个片段。我尝试了一些计算来获取当前的片段,但没有成功。
那么,关于如何计算循环中的 uvShadow 有什么想法吗?
我希望我也使用好的变量,因为在我的代码的最后一部分,我使用 gl_FragColor,我使用 uvVarying 来获取当前片段(如果我没记错的话),但要得到光的距离,我必须计算 posVarying 和 lightPos 之间的长度,而不是 uvVarying 和 lightPos 之间的长度(我做了一个测试,我离光越远,它变得越红,而使用 posVarying,它使我变成了一个圆圈我的播放器周围有渐变(lightPos),但是当我使用 uvVarying 时,圆圈只有一种颜色,当我将播放器靠近屏幕中心时,它或多或少是红色)。
谢谢和最好的问候,
最大
【问题讨论】:
标签: opengl-es textures glsl shader shadow