由于gl_位置,opengl纹理坐标插值不正确
我正在使用LWJGL java制作opengl关节动画。我所有的关节和顶点都按预期正确变换,但当我使用纹理渲染模型时,奇怪的事情开始发生 顶点着色器代码由于gl_位置,opengl纹理坐标插值不正确,opengl,lwjgl,vertex-shader,Opengl,Lwjgl,Vertex Shader,我正在使用LWJGL java制作opengl关节动画。我所有的关节和顶点都按预期正确变换,但当我使用纹理渲染模型时,奇怪的事情开始发生 顶点着色器代码 # version 430 core uniform mat4 projection, view, model; in vec3 vertex; uniform mat4 rotate; in vec2 texCoord; out vec2 vertexTexCoord; uniform mat4 joints[16]; in ivec4
# version 430 core
uniform mat4
projection,
view,
model;
in vec3 vertex;
uniform mat4 rotate;
in vec2 texCoord;
out vec2 vertexTexCoord;
uniform mat4 joints[16];
in ivec4 jointIndices;
in vec4 weights;
in vec3 normal;
const vec3 directions[3]={vec3(0,-1,0),vec3(0,1,0),vec3(0,0,-1)};
out vec3 vertexNormal;
out vec3 lighting[3];
void main()
{
mat4 modelRotate=(model*rotate);
vec4 finalVertex=vec4(0.0);
vec4 finalNormal=vec4(0.0);
for(int i=0;i<4;i++)
{
mat4 jointTransform=joints[jointIndices[i]];
vec4 modelVertex=vec4(vertex,1.0);
vec4 posVertex=jointTransform*modelVertex;
finalVertex+=posVertex*weights[i];
vec4 modelNormal=vec4(normal,0.0);
vec4 poseNormal=jointTransform*modelNormal;
finalNormal+=poseNormal*weights[i];
}
gl_Position=projection*view*modelRotate*vec4(vertex,1.0);
vertexNormal=(modelRotate*finalNormal).xyz;
for(int i=0;i<3;i++){lighting[i]=directions[i]*-1;}
vertexTexCoord=texCoord;
}
#version 430 core
in vec3 vertexNormal;
in vec3 lighting[3];
in vec2 vertexTexCoord;
uniform sampler2D tex;
out vec4 pixelColor;
void main()
{
vec3 nNormal=normalize(vertexNormal);
vec3 lightColor=vec3(0.0);
for(int i=0;i<3;i++)
{
vec3 nLight=normalize(lighting[i]);
float nDot=max(0.0,dot(nNormal,nLight));
lightColor+=vec3(1,1,1)*nDot;
}
pixelColor=vec4(vertexTexCoord.x,vertexTexCoord.y,0,0);
}
什么时候
也就是说,我的模型使用原始输入顶点,而不是转换的finalVertex
输出
正如您所看到的,每个曲面上的纹理坐标都应该是不同的,这是正确的
因此,当我使用这些纹理坐标的正确纹理渲染我的模型时,通过将我的pixelColor更改为
pixelColor=texture(tex,vertexTexCoord);
输出
我的模型在正确的位置使用纹理正确渲染
现在事情从这一点上变得很奇怪
将我的着色器代码更改为
gl_Position=projection*view*modelRotate*finalVertex;
pixelColor=vec4(vertexTexCoord.x,vertexTexCoord.y,0,0);
pixelColor=texture(tex,vertexTexCoord);
现在,我的模型使用来自每个关节的最终变换顶点,我的片段着色器输出纹理坐标。
输出应该与上面的文字相同,没有任何变化,但是我得到了这个 输出 现在,整个模型中的纹理坐标完全相同,根本不进行插值。他们都是统一的 现在,当我通过将片段着色器代码更改为
gl_Position=projection*view*modelRotate*finalVertex;
pixelColor=vec4(vertexTexCoord.x,vertexTexCoord.y,0,0);
pixelColor=texture(tex,vertexTexCoord);
输出如预期的,而不是我预期的:
输出:
如果有帮助,这里是我的模型纹理。我从教程下载的
似乎纹理坐标被粘在了图像的左上角,这可能解释了为什么我的模型是全黑色的,因为在左上角有很多黑色区域
因此,通过将顶点着色器中的一行代码从
gl_Position=projection*view*modelRotate*vec4(vertex,1.0);
TO
gl_Position=projection*view*modelRotate*finalVertex;
它改变了我的生活
为此:
任何来自任何地方的建议,无论是重塑我的角色或纹理,还是创建新的渲染引擎,我们都将不胜感激
编写加载模型和联合变换以及层次结构的代码花了我4天的时间
两周后,我仍然无法找出我的着色器出了什么问题。
多谢各位
我这里有一个简单的静态着色器,可以加载一个统一的矩阵
public abstract class StaticShader
{
private int
programID=0,
vertexShaderID=0,
fragmentShaderID=0,
infoLogSize=0;
private final FloatBuffer mat4fBuffer=BufferUtils.createFloatBuffer(16);
protected StaticShader(Object vertexShader,Object fragmentShader)
{
programID=GL20.glCreateProgram();
vertexShaderID=loadShader(vertexShader,GL20.GL_VERTEX_SHADER);
fragmentShaderID=loadShader(fragmentShader,GL20.GL_FRAGMENT_SHADER);
GL20.glAttachShader(programID,vertexShaderID);
GL20.glAttachShader(programID,fragmentShaderID);
bindAttributes();
GL20.glLinkProgram(programID);
if(GL20.glGetProgrami(programID,GL20.GL_LINK_STATUS)==GL11.GL_FALSE)
{
infoLogSize=GL20.glGetProgrami(programID,GL20.GL_INFO_LOG_LENGTH);
System.err.println(GL20.glGetProgramInfoLog(programID,infoLogSize));
System.err.println("COULD NOT LINK SHADER");
System.exit(-1);
}
GL20.glValidateProgram(programID);
if(GL20.glGetProgrami(programID,GL20.GL_VALIDATE_STATUS)==GL11.GL_FALSE)
{
infoLogSize=GL20.glGetProgrami(programID,GL20.GL_INFO_LOG_LENGTH);
System.err.println(GL20.glGetProgramInfoLog(programID,infoLogSize));
System.err.println("COULD NOT VALIDATE SHADER");
System.exit(-1);
}
}
protected void bindAttribute(int attribno,String variable){GL20.glBindAttribLocation(programID,attribno,variable);}
abstract void bindAttributes();
private int loadShader(Object src,int shaderType)
{
StringBuilder source=Utils.loadSource(src);
int shaderID=GL20.glCreateShader(shaderType);
GL20.glShaderSource(shaderID,source);
GL20.glCompileShader(shaderID);
if(GL20.glGetShaderi(shaderID,GL20.GL_COMPILE_STATUS)==GL11.GL_FALSE)
{
infoLogSize=GL20.glGetShaderi(shaderID,GL20.GL_INFO_LOG_LENGTH);
System.err.println(GL20.glGetShaderInfoLog(shaderID,infoLogSize));
System.err.println("COULD NOT COMPILE SHADER");
System.exit(-1);
}
return shaderID;
}
public void start(){GL20.glUseProgram(programID);}
public void stop(){GL20.glUseProgram(0);}
public void release()
{
GL20.glUseProgram(0);
GL20.glDetachShader(programID,vertexShaderID);
GL20.glDetachShader(programID,fragmentShaderID);
GL20.glDeleteShader(vertexShaderID);
GL20.glDeleteShader(fragmentShaderID);
}
public void loadMatrix(String name,Matrix4f mat)
{
start();
mat.store(mat4fBuffer);
mat4fBuffer.flip();
GL20.glUniformMatrix4(GL20.glGetUniformLocation(programID,name),false,mat4fBuffer);
stop();
}
}
从这个着色器中,我继承了MyShader类
public class MyShader extends StaticShader
{
private static final String
VERTEX_SHADER="/main/animate.VS",
FRAGMENT_SHADER="/main/animate.FS";
private Texture tex;
public MyShader()
{
super(VERTEX_SHADER,FRAGMENT_SHADER);
Matrix4f mat=new Matrix4f();
try
{
InputStream is=MyShader.class.getResourceAsStream("Character Texture.png");
tex=TextureLoader.getTexture(".png",is,true);
is.close();
}
catch(Exception ex){ex.printStackTrace();}
float aspectRatio=(float)Display.getWidth()/(float)Display.getHeight();
Utils.perspective(50,0.1f,1000,aspectRatio,mat);
super.loadMatrix("projection",mat);/*PERSPECTIVE MATRIX*/
Vector3f location=new Vector3f(0,4,12);
Vector3f lookAt=new Vector3f(0,4,0);
Vector3f up=new Vector3f(0,1,0);
Utils.lookAt(location,lookAt,up,mat);
super.loadMatrix("view",mat); /*VIEW MATRIX*/
mat.setIdentity();
mat.scale(new Vector3f(1.2f,1,1));
super.loadMatrix("model",mat); /*MODEL MATRIX*/
mat.setIdentity();
mat.rotate((float)Math.toRadians(90),new Vector3f(-1,0,0));
super.loadMatrix("rotate",mat); /*FLIP MODEL BY 90 DEGRESS*/
for(int i=0;i<16;i++)
{
mat.setIdentity();/*LOAD ALL JOINT TRANSFORM'S AS IDENTITY*/
super.loadMatrix("joints["+String.valueOf(i)+"]",mat);
}
}
public void bindAttributes()
{
super.bindAttribute(0,"vertex");
super.bindAttribute(1,"normal");
super.bindAttribute(2,"texCoord");
super.bindAttribute(3,"jointIndices");
super.bindAttribute(4,"weights");
}
public void start()
{
super.start();
GL13.glActiveTexture(GL13.GL_TEXTURE0);
GL11.glBindTexture(GL11.GL_TEXTURE_2D,tex.getTextureID());
}
public void release()
{
tex.release();
super.release();
}
}
我的暂停正在将矩阵加载到制服数组中,但我不确定。谢谢你,我发现链接数据时问题不在于着色器或模型,而在于网格渲染器 如果必须将整数数据链接到着色器[linking jointId],则必须使用
GL30.glVertexAttribIPointer(index,vecType,GL11.GL_INT,0,0)
And not
GL20.glVertexAttribPointer(index,vectype,GL11.GL_INT,false,0,0);
我不知道为什么他们会用一个单独的方法来链接integer,但这让我的纹理工作得非常完美。大小写结束输出应与上述文字相同。没有任何变化,没有任何变化?实际上有很多变化,包括潜在的所有统一位置以及属性位置。好吧,您根本没有发布相关代码,因此没有人可以给出任何具体建议。我的第一个怀疑是您没有正确地处理或指定属性和/或统一位置。不,我们不会整理您的代码库的相关位。您必须提供一个。好的,您可以通过查询着色器正在使用的实际属性位置,并检查它正在使用/假定的VAO设置代码来缩小范围。问题中的代码不完整,同时,它也远远不是最小的。这不是stackoverflow上的定义方式。您需要将代码添加到问题本身。而且你的东西也不是最小的。例如,不需要复杂的模型文件来演示问题。一个三角形就足够了,这个三角形可以直接在源代码中定义。纹理文件是完全不相关的。这不是把你的东西上传到什么地方。它是关于迭代地剥离代码和数据,直到达到演示问题所需的绝对最小值。
public class Main
{
/*DISPLAY ATTRIBUTES*/
private static ContextAttribs createDisplayAttributes()
{
ContextAttribs attribs=new ContextAttribs(4,2)
.withForwardCompatible(true)
.withProfileCore(true);
return attribs;
}
private static void initDisplay(String title)
{
try
{
Display.create(new PixelFormat(),createDisplayAttributes());
Display.setTitle(title);
Display.setDisplayMode(new DisplayMode(1500,705));
Display.setLocation(0,-2);
Display.setResizable(false);
}
catch(Exception e)
{
e.printStackTrace();
}
}
/*DISPLAY ATTRIBUTES*/
private static void startFrame()
{
GL11.glClear(GL11.GL_COLOR_BUFFER_BIT | GL11.GL_DEPTH_BUFFER_BIT);
GL11.glEnable(GL11.GL_DEPTH_TEST);
GL11.glClearColor(0,0,1,0);
}
public static void main(String args[])
{
initDisplay("ANIMATION TEST");
MeshRender mesh=MeshRender.createMesh();
MyShader myShader=new MyShader();
while(!Display.isCloseRequested())
{
startFrame();
myShader.start();
mesh.render();
myShader.stop();
updateDisplay();
}
mesh.release();
myShader.release();
mesh.release();
releaseOpenGL();
}
private static void updateDisplay()
{
Display.update();
Display.sync(60);
}
private static void releaseOpenGL()
{
try
{
Mouse.destroy();
Keyboard.destroy();
Display.releaseContext();
Display.destroy();
}
catch(Exception ex){ex.printStackTrace();}
}
GL30.glVertexAttribIPointer(index,vecType,GL11.GL_INT,0,0)
And not
GL20.glVertexAttribPointer(index,vectype,GL11.GL_INT,false,0,0);