This
1、什么坐标系?
最后,这取决于你。坐标系只需要满足一些要求。它必须保持角度(因为照明都是关于角度的)。如果需要基于距离的衰减,也应该保持距离。世界坐标系和视图坐标系通常满足这些要求。剪辑空间不适用于照明计算,因为既不保留角度也不保留距离。此外
gl_PointCoord
不在任何常用坐标系中。它是自己的坐标系,只有知道其他坐标系的关系时,才应将其与其他坐标系一起使用。
2、网格还是什么?
网格绝对不适合渲染球体。如上所述,光线投射或一些屏幕空间近似是更好的选择。以下是我在项目中使用的示例着色器:
#version 330
out vec4 result;
in fData
{
vec4 toPixel; //fragment coordinate in particle coordinates
vec4 cam; //camera position in particle coordinates
vec4 color; //sphere color
float radius; //sphere radius
} frag;
uniform mat4 p; //projection matrix
void main(void)
{
vec3 v = frag.toPixel.xyz - frag.cam.xyz;
vec3 e = frag.cam.xyz;
float ev = dot(e, v);
float vv = dot(v, v);
float ee = dot(e, e);
float rr = frag.radius * frag.radius;
float radicand = ev * ev - vv * (ee - rr);
if(radicand < 0)
discard;
float rt = sqrt(radicand);
float lambda = max(0, (-ev - rt) / vv); //first intersection on the ray
float lambda2 = (-ev + rt) / vv; //second intersection on the ray
if(lambda2 < lambda) //if the first intersection is behind the camera
discard;
vec3 hit = lambda * v; //intersection point
vec3 normal = (frag.cam.xyz + hit) / frag.radius;
vec4 proj = p * vec4(hit, 1); //intersection point in clip space
gl_FragDepth = ((gl_DepthRange.diff * proj.z / proj.w) + gl_DepthRange.near + gl_DepthRange.far) / 2.0;
vec3 vNormalized = -normalize(v);
float nDotL = dot(vNormalized, normal);
vec3 c = frag.color.rgb * nDotL + vec3(0.5, 0.5, 0.5) * pow(nDotL, 120);
result = vec4(c, frag.color.a);
}
3、视角划分
透视分割不应用于属性。GPU对您通过的数据进行透视分割
gl_Position
4、黑暗中的光明
这可能是混合不同坐标系或在剪辑空间中进行照明计算的结果。顺便说一句,镜面反射部分通常不会乘以材质颜色。这是直接在表面反射的光。它不会穿透表面(根据材料的不同,表面会吸收一些颜色)。这就是为什么即使在黑色物体上,这些高光通常都是白色(或任何你拥有的浅色)。