用于纹理三次投影的GLSL着色器 [英] GLSL shader for texture cubic projection
问题描述
我正在尝试在WebGL着色器中实现纹理三次投影,如下图所示:
I am trying to implement a texture cubic projection inside my WebGL shader, like in the picture below:
到目前为止我尝试过的事情:
What I tried so far:
我正在传递对象的边界框(图片中间的框),如下所示:
I am passing the bounding box of my object (the box in the middle of the picture) as follows:
uniform vec3 u_bbmin;
uniform vec3 u_bbmax;
...所以我的投影框的八个顶点是:
... so the eight vertexes of my projection box are:
vec3 v1 = vec3(u_bbmin.x, u_bbmin.y, u_bbmin.z);
vec3 v2 = vec3(u_bbmax.x, u_bbmin.y, u_bbmin.z);
vec3 v3 = vec3(u_bbmin.x, u_bbmax.y, u_bbmin.z);
...other combinations
vec3 v8 = vec3(u_bbmax.x, u_bbmax.y, u_bbmax.z);
最后,要从我的纹理中采样,我需要一个以下形式的地图:
At the end, to sample from my texture I need a map in the form of:
varying vec3 v_modelPos;
...
uniform sampler2D s_texture;
vec2 tCoords = vec2(0.0);
tCoords.s = s(x,y,z)
tCoords.t = t(y,y,z)
vec4 color = texture2D(s_texture, tCoords);
我能够实现球面和圆柱投影,但是现在我被困在如何获得这种立方贴图的过程中,纹理将延伸到整个边界框,长宽比无关紧要.
I was able to implement spherical and cylindrical projections, but I am stuck now how to get this kind of cubic map, The texture shall stretch to the whole bounding box, aspect ratio doesn't matter.
也许我缺少一些关键点,并且我需要一些提示.三次投影的数学应如何显示?
Maybe I am missing some key points and I need some hints. How should the math for a cubic projection looks like?
推荐答案
此处的重点是:法线应在对象空间中.请注意,通过使用uv
计算矩阵, gman 的答案比我的答案更为优雅.我使用的是边界框坐标,该坐标已作为uniform
传递给顶点着色器,用于其他常规用途.
The key-point here is: normals shall be in object-space. Please note that gman's answer is more elegant than mine, by using a matrix for the uv
computation. I am using instead the bounding box coordinates, which are already passed to the vertex shader as uniform
for other general purposes.
此外,我什至不需要区分所有六个主轴,我只需要三个侧面投影,因此可以简化下来.当然,纹理会镜像到相对的面上.
Moreover, I don't even need to distinguish all the six major axis, I just only need three sides projection, so this can be simplified down. Of course, the texture will be mirrored on the opposite faces.
float sX = u_bbmax.x - u_bbmin.x;
float sY = u_bbmax.y - u_bbmin.y;
float sZ = u_bbmax.z - u_bbmin.z;
/* --- BOX PROJECTION - THREE SIDES --- */
if( (abs(modelNormal.x) > abs(modelNormal.y)) && (abs(modelNormal.x) > abs(modelNormal.z)) ) {
uvCoords = modelPos.yz / vec2(sY, -sZ); // X axis
} else if( (abs(modelNormal.z) > abs(modelNormal.x)) && (abs(modelNormal.z) > abs(modelNormal.y)) ) {
uvCoords = modelPos.xy / vec2(sX, -sY); // Z axis
} else {
uvCoords = modelPos.xz / vec2(sX, -sZ); // Y axis
}
uvCoords += vec2(0.5);
说明:
- 纹理投影的方向由
modelPos
坐标的顺序. 示例:可以使用将纹理旋转90度modelPos.yx
而不是modelPos.xy
. - 纹理投影的方向由的符号决定
modelPos
坐标. 示例:可以使用来在Y轴上镜像纹理vec2(sX, sY)
而不是vec2(sX, -sY)
.
- The direction of the texture projection is determined by the
order of the
modelPos
coordinates. Example: the texture can be rotated by 90 degrees by usingmodelPos.yx
instead ofmodelPos.xy
. - The orientation of the texture projection is determined by the sign of
the
modelPos
coordinates. Example: the texture can be mirrored on the Y-axis by usingvec2(sX, sY)
instead ofvec2(sX, -sY)
.
结果:
值得在这里链接 gman 的另一个答案,其中包含有关此主题的其他信息以及一些很酷的优化技术为了避免在GLSL着色器中使用条件:如何使用6 sampler2D来实现textureCube .
It is worth to link here another answer from gman which contain additional information about this topic and also some cool optimization techniques to avoid conditionals inside GLSL shaders: How to implement textureCube using 6 sampler2D.
这篇关于用于纹理三次投影的GLSL着色器的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!