Opengl es 如何使用立方体贴图对未展开的模型进行纹理处理

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

我有很多没有展开的模型(它们没有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;
   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)
不在网格内,也会出现瑕疵

我将从计算网格的BBOX
BBOXmin(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);
    }
//------------------------------------------------------------------