Opengl es 如何使用立方体贴图对未展开的模型进行纹理处理
我有很多没有展开的模型(它们没有UV坐标)。打开它们很复杂。因此,我决定使用无缝立方体贴图对其进行纹理处理:Opengl es 如何使用立方体贴图对未展开的模型进行纹理处理,opengl-es,libgdx,glsl,opengl-es-2.0,Opengl Es,Libgdx,Glsl,Opengl Es 2.0,我有很多没有展开的模型(它们没有UV坐标)。打开它们很复杂。因此,我决定使用无缝立方体贴图对其进行纹理处理: [VERT] attribute vec4 a_position; varying vec3 texCoord; uniform mat4 u_worldTrans; uniform mat4 u_projTrans; ... void main() { gl_Position = u_projTrans * u_worldTrans * a_position; te
[VERT]
attribute vec4 a_position;
varying vec3 texCoord;
uniform mat4 u_worldTrans;
uniform mat4 u_projTrans;
...
void main()
{
gl_Position = u_projTrans * u_worldTrans * a_position;
texCoord = vec3(a_position);
}
[FRAG]
varying vec3 texCoord;
uniform samplerCube u_cubemapTex;
void main()
{
gl_FragColor = textureCube(u_cubemapTex, texCoord);
}
这是可行的,但结果很奇怪,因为纹理取决于顶点的位置。如果我的模型比立方体或球体更复杂,我会在对象的某些部分看到可见的接缝和低分辨率的纹理
反射在模型上映射良好,但具有镜像效果
反思:
[VERT]
attribute vec3 a_normal;
varying vec3 v_reflection;
uniform mat4 u_matViewInverseTranspose;
uniform vec3 u_cameraPos;
...
void main()
{
mat3 normalMatrix = mat3(u_matViewInverseTranspose);
vec3 n = normalize(normalMatrix * a_normal);
//calculate reflection
vec3 vView = a_position.xyz - u_cameraPos.xyz;
v_reflection = reflect(vView, n);
...
}
如何实现反射之类的效果,但具有“粘性”效果,这意味着纹理好像附着到某个顶点(不移动)。模型的每一侧都必须显示立方体贴图自己的一侧,因此它应该看起来像普通的2D纹理。如有任何建议,将不胜感激
更新1
我总结了所有的评论,并决定计算立方体贴图UV。由于我使用LibGDX,一些名称可能与OpenGL不同
着色器类:
public class CubemapUVShader implements com.badlogic.gdx.graphics.g3d.Shader {
ShaderProgram program;
Camera camera;
RenderContext context;
Matrix4 viewInvTraMatrix, viewInv;
Texture texture;
Cubemap cubemapTex;
...
@Override
public void begin(Camera camera, RenderContext context) {
this.camera = camera;
this.context = context;
program.begin();
program.setUniformMatrix("u_matProj", camera.projection);
program.setUniformMatrix("u_matView", camera.view);
cubemapTex.bind(1);
program.setUniformi("u_textureCubemap", 1);
texture.bind(0);
program.setUniformi("u_texture", 0);
context.setDepthTest(GL20.GL_LEQUAL);
context.setCullFace(GL20.GL_BACK);
}
@Override
public void render(Renderable renderable) {
program.setUniformMatrix("u_matModel", renderable.worldTransform);
viewInvTraMatrix.set(camera.view);
viewInvTraMatrix.mul(renderable.worldTransform);
program.setUniformMatrix("u_matModelView", viewInvTraMatrix);
viewInvTraMatrix.inv();
viewInvTraMatrix.tra();
program.setUniformMatrix("u_matViewInverseTranspose", viewInvTraMatrix);
renderable.meshPart.render(program);
}
...
}
顶点:
attribute vec4 a_position;
attribute vec2 a_texCoord0;
attribute vec3 a_normal;
attribute vec3 a_tangent;
attribute vec3 a_binormal;
varying vec2 v_texCoord;
varying vec3 v_cubeMapUV;
uniform mat4 u_matProj;
uniform mat4 u_matView;
uniform mat4 u_matModel;
uniform mat4 u_matViewInverseTranspose;
uniform mat4 u_matModelView;
void main()
{
gl_Position = u_matProj * u_matView * u_matModel * a_position;
v_texCoord = a_texCoord0;
//CALCULATE CUBEMAP UV (WRONG!)
//I decided that tm_l2g mentioned in comments is u_matView * u_matModel
v_cubeMapUV = vec3(u_matView * u_matModel * vec4(a_normal, 0.0));
/*
mat3 normalMatrix = mat3(u_matViewInverseTranspose);
vec3 t = normalize(normalMatrix * a_tangent);
vec3 b = normalize(normalMatrix * a_binormal);
vec3 n = normalize(normalMatrix * a_normal);
*/
}
片段:
varying vec2 v_texCoord;
varying vec3 v_cubeMapUV;
uniform sampler2D u_texture;
uniform samplerCube u_textureCubemap;
void main()
{
vec3 cubeMapUV = normalize(v_cubeMapUV);
vec4 diffuse = textureCube(u_textureCubemap, cubeMapUV);
gl_FragColor.rgb = diffuse;
}
结果是完全错误的:
我期待这样的事情:
更新2
如果在顶点着色器中使用顶点位置作为立方体贴图坐标,则纹理看起来在侧面拉伸,在某些位置扭曲:
v_cubeMapUV = a_position.xyz;
我上传了,还有要审查的文件 该代码仅适用于以
(0,0,0)
为中心的网格,如果情况并非如此,或者即使(0,0,0)
不在网格内,也会出现瑕疵
我将从计算网格的BBOXBBOXmin(x0,y0,z0),BBOXmax(x1,y1,z1)
开始,并平移纹理坐标所用的位置,使其围绕它居中:
center = 0.5*(BBOXmin+BBOXmax);
texCoord = vec3(a_position-center);
但是,不均匀的顶点密度仍然会导致纹理缩放瑕疵,特别是当BBOX边的大小差异过大时。将其重新缩放为多维数据集将有助于:
vec3 center = 0.5*(BBOXmin+BBOXmax); // center of BBOX
vec3 size = BBOXmax-BBOXmin; // size of BBOX
vec3 r = a_position-center; // position centered around center of BBOX
r.x/=size.x; // rescale it to cube BBOX
r.y/=size.y;
r.z/=size.z;
texCoord = r;
同样,如果BBOX的中心不在网格内,那么这将不起作用
反射部分我不清楚你有一些图像/截图吗
[Edit1]简单示例
我是这样看的(没有上面提到的中心偏移和纵横比修正):
[顶点]
//------------------------------------------------------------------
#版本420核心
//------------------------------------------------------------------
均匀mat4x4 tm_l2g;
统一的mat4x4 tm_g2s;
vec3位置中的布局(位置=0);
vec4列中的布局(位置=1);
输出平滑矢量4像素;
输出平滑vec3像素\u txr;
//------------------------------------------------------------------
真空总管(真空)
{
像素_col=col;
像素×txr=(tm×l2g*vec4(位置,0.0)).xyz;
gl_位置=tm_g2s*tm_l2g*vec4(位置,1.0);
}
//------------------------------------------------------------------
[Fragment]
//------------------------------------------------------------------
#版本420核心
//------------------------------------------------------------------
在平滑vec4像素列中;
在平滑vec3像素中\u txr;
统一采样器立方体txr_skybox;
输出布局(位置=0)矢量4框架;
//------------------------------------------------------------------
真空总管(真空)
{
frag_col=纹理(txr_skybox,pixel_txr);
}
//------------------------------------------------------------------
在此预览:
前几帧中的白色圆环体使用固定函数,其余部分使用着色器。正如您所看到的,我使用的唯一输入是顶点位置、颜色和变换矩阵tm_l2g
,它将网格坐标转换为全局坐标,并tm_g2s
保存透视投影
如您所见,我使用与渲染模型相同的立方体贴图纹理渲染BBOX,因此它看起来像很酷的反射/透明度效果:)(这不是有意的)
不管怎样,当我换线的时候
pixel_txr=(tm_l2g*vec4(pos,0.0)).xyz;
进入:
在我的顶点着色器中,对象将再次成为实体:
您可以通过传递两个纹理坐标向量并在片段中获取两个texel将它们以一定比例相加来组合这两个纹理坐标向量。对于粗糙,您需要传递2个立方体贴图纹理,一个用于对象,一个用于skybox
红色警告来自我的CPU端代码,提醒我正在尝试设置着色器中不存在的制服(正如我在不更改CPU端代码的情况下从中所做的…)
[Edit1]此处预览带有偏移的网格
顶点有点变化(只是添加了答案中描述的偏移):
因此,通过偏移中心点,您可以消除奇点失真。然而,正如我在评论中提到的,对于任意网格,使用廉价的纹理技巧而不是正确的纹理坐标,总会出现一些失真
请注意,我的网格已调整大小/规格化(遗憾的是,我不记得它的
范围或不同的ona,并且懒得在我测试此功能的GLSL引擎的源代码中挖掘),因此偏移量在您的环境中可能具有不同的大小,以实现相同的结果。我的网格居中(0,0,0)。我从不移动它,只是绕着它旋转一个摄像头。可以不使用顶点位置(a_位置)生成纹理坐标吗?您可以在Internet上到处找到反射部分的实现。例如,@Nolesh我知道反射是什么,但你想的是什么?我猜(但这里只是猜测)?这与纹理坐标或顶点位置无关。它只使用面法线。。。除非它是“真实的”,并且基于相机的位置……通过反射,我的意思是它不使用顶点位置,在我的例子中可能会很有用。由于伪影,我不能依赖顶点位置。是
pixel_txr=pos;
//------------------------------------------------------------------
#version 420 core
//------------------------------------------------------------------
uniform mat4x4 tm_l2g;
uniform mat4x4 tm_g2s;
uniform vec3 center=vec3(0.0,0.0,2.0);
layout(location=0) in vec3 pos;
layout(location=1) in vec4 col;
out smooth vec4 pixel_col;
out smooth vec3 pixel_txr;
//------------------------------------------------------------------
void main(void)
{
pixel_col=col;
pixel_txr=pos-center;
gl_Position=tm_g2s*tm_l2g*vec4(pos,1.0);
}
//------------------------------------------------------------------