我正在使用LWJGL java进行opengl联合动画。我所有的关节和顶点都按预期正确转换,但是当我使用纹理渲染模型时,奇怪的东西开始发生
VertexShader代码
# 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;
}
FragmentShader Code
#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);
}
我没有在我的模型中使用灯光,因为它已经过测试并且工作正常,但它是我的纹理坐标是不正确的,所以我在我的着色器中将它们输出为红色,绿色组合用于调试
每个着色器中有两行代码需要注意
VertexShader: gl_Position
FragmentShader: pixelColor
何时
gl_Position=projection*view*modelRotate*vec4(vertex,1.0);
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*vec4(vertex,1.0);
TO
gl_Position=projection*view*modelRotate*finalVertex;
To This :(
任何地方的任何建议,无论是重塑我的角色或纹理,还是创建新的渲染引擎,都会非常感激。
编写代码以加载模型和联合变换和层次结构花了我4天的工作
2周后,我仍然无法弄清楚我的着色器有什么问题。 谢谢
我这里有一个简单的静态着色器,可以加载一个统一的矩阵
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();
}
}
接下来,我们有一个几何渲染器,它从二进制文件加载模型并将内容渲染到屏幕上。
public class MeshRender
{
private final int vao;
private final ArrayList<Integer> vbos=new ArrayList<Integer>();
private final ArrayList<Integer> indexLocations=new ArrayList<Integer>();
private final int vertexCount;
public MeshRender(int vertices)
{
vao=GL30.glGenVertexArrays();
GL30.glBindVertexArray(vao);
vertexCount=vertices;
}
public void createAttribute(int index,int vectype,FloatBuffer buffer)
{
int vbo=GL15.glGenBuffers();
GL15.glBindBuffer(GL15.GL_ARRAY_BUFFER,vbo);
GL15.glBufferData(GL15.GL_ARRAY_BUFFER,buffer,GL15.GL_DYNAMIC_DRAW);
GL20.glVertexAttribPointer(index,vectype,GL11.GL_FLOAT,false,0,0);
GL15.glBindBuffer(GL15.GL_ARRAY_BUFFER,0);
indexLocations.add(index);
vbos.add(vbo);
}
public void createAttribute(int index,int vectype,IntBuffer buffer)
{
int vbo=GL15.glGenBuffers();
GL15.glBindBuffer(GL15.GL_ARRAY_BUFFER,vbo);
GL15.glBufferData(GL15.GL_ARRAY_BUFFER,buffer,GL15.GL_DYNAMIC_DRAW);
GL20.glVertexAttribPointer(index,vectype,GL11.GL_INT,false,0,0);
GL15.glBindBuffer(GL15.GL_ARRAY_BUFFER,0);
indexLocations.add(index);
vbos.add(vbo);
}
public void unBind(){GL30.glBindVertexArray(0);}
public void render()
{
GL30.glBindVertexArray(vao);
for(int index: indexLocations){GL20.glEnableVertexAttribArray(index);}
GL11.glDrawArrays(GL11.GL_TRIANGLES,0,vertexCount);
for(int index: indexLocations){GL20.glDisableVertexAttribArray(index);}
GL30.glBindVertexArray(0);
}
public void release()
{
for(int vbo: vbos){GL15.glDeleteBuffers(vbo);}
GL30.glDeleteVertexArrays(vao);
}
public static MeshRender createMesh()
{
MeshRender mesh=null;
try
{
Model model=Model.readFromFile("/main/Model.data");
FloatBuffer fBuffer;
IntBuffer iBuffer;
fBuffer=model.toFBuffer(0);
mesh=new MeshRender(fBuffer.capacity()/3);
mesh.createAttribute(0,3,fBuffer);/*VERTICES' INDEX=0 FLOAT'S=3*/
fBuffer=model.toFBuffer(1);
mesh.createAttribute(1,3,fBuffer);/*NORMAL'S INDEX=1 FLOAT'S=3*/
fBuffer=model.toFBuffer(2);
mesh.createAttribute(2,2,fBuffer);/*TEX COORD'S INDEX=2 FLOAT'S=2*/
iBuffer=model.toIBuffer(3);
mesh.createAttribute(3,4,iBuffer);/*JOINT INDICES INDEX=3 INT'S=4*/
fBuffer=model.toFBuffer(4);
mesh.createAttribute(4,4,fBuffer);/*WEIGHT'S INDEX=4 FLOAT'S=4*/
mesh.unBind();
}
catch(Exception ex){ex.printStackTrace();}
return mesh;
}
}
班级模型是从文件中加载的实际数据,工作正常。但是你可以在这里加载你想要的任何信息。
最后,我的着色器和几何体在我的主要课堂中一起使用
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();}
}
我的悬架正在为一系列制服加载矩阵,但我不确定。谢谢你
答案 0 :(得分:1)
嗯我发现问题不是我的着色器或我的模型,而是链接数据时我的MeshRenderer。
如果必须将整数数据链接到着色器[链接jointId],则必须使用
GL30.glVertexAttribIPointer(index,vecType,GL11.GL_INT,0,0)
And not
GL20.glVertexAttribPointer(index,vectype,GL11.GL_INT,false,0,0);
不知道为什么他们为连接整数做了一个单独的方法,但这使我的纹理完美地运作。案件结案