我遇到一个问题:着色器无法再编译。
如果有帮助,我认为它可能是 Renderer 类中的东西。
MainGameLoop 类:
package engineStarter;
import models.RawModel;
import models.TexturedModel;
import org.lwjgl.opengl.Display;
import org.lwjgl.util.vector.Vector3f;
import renderEngine.DisplayManager;
import renderEngine.Loader;
import renderEngine.OBJLoader;
import renderEngine.Renderer;
import shaders.StaticShader;
import textures.ModelTexture;
import entities.Camera;
import entities.Entity;
import entities.Light;
public class MainGameLoop {
public static void main(String[] args) {
DisplayManager.createDisplay();
Loader loader = new Loader();
System.out.println("Gameloop");
StaticShader shader = new StaticShader();
Renderer renderer = new Renderer(shader);
//RawModel model = loader.loadToVAO(vertices, textureCoords, indices);
RawModel model = OBJLoader.loadObjModel("stall", loader);
System.out.println(model);
TexturedModel staticModel = new TexturedModel(model,new ModelTexture(loader.loadTexture("stallTexture")));
Entity entity = new Entity(staticModel, new Vector3f(0,0,-50),0,0,0,1);
Light light = new Light(new Vector3f(0, 0, -20), new Vector3f(1,1,1));
Camera camera = new Camera();
while(!Display.isCloseRequested()){
System.out.println("Display Running");
entity.increaseRotation(0, 1, 0);
entity.increasePosition(0, 0, 0);
camera.move();
renderer.prepare();
shader.start();
shader.loadLight(light);
shader.loadViewMatrix(camera);
renderer.render(entity,shader);
shader.stop();
DisplayManager.updateDisplay();
}
shader.cleanUp();
loader.cleanUp();
DisplayManager.closeDisplay();
}
}
渲染器类:
package renderEngine;
import models.RawModel;
import models.TexturedModel;
import org.lwjgl.opengl.Display;
import org.lwjgl.opengl.GL11;
import org.lwjgl.opengl.GL13;
import org.lwjgl.opengl.GL20;
import org.lwjgl.opengl.GL30;
import org.lwjgl.util.vector.Matrix4f;
import shaders.StaticShader;
import toolbox.Maths;
import entities.Entity;
public class Renderer {
private static final float FOV = 70;
private static final float NEAR_PLANE = 0.1f;
private static final float FAR_PLANE = 1000;
private Matrix4f projectionMatrix;
public Renderer(StaticShader shader){
createProjectionMatrix();
shader.start();
shader.loadProjectionMatrix(projectionMatrix);
shader.stop();
}
public void prepare() {
GL11.glEnable(GL11.GL_DEPTH_TEST);
GL11.glClear(GL11.GL_COLOR_BUFFER_BIT|GL11.GL_DEPTH_BUFFER_BIT);
GL11.glClearColor(0, 0.0f, 0.0f, 1);
}
public void render(Entity entity, StaticShader shader) {
TexturedModel model = entity.getModel();
RawModel rawModel = model.getRawmodel();
GL30.glBindVertexArray(rawModel.getVaoID());
GL20.glEnableVertexAttribArray(0);
GL20.glEnableVertexAttribArray(1);
GL20.glEnableVertexAttribArray(2);
Matrix4f transformationMatrix = Maths.createTransformationMatrix(entity.getPosition(),
entity.getRotX(), entity.getRotY(), entity.getRotZ(), entity.getScale());
shader.loadTransformationMatrix(transformationMatrix);
GL13.glActiveTexture(GL13.GL_TEXTURE0);
GL11.glBindTexture(GL11.GL_TEXTURE_2D, model.getTexture().getID());
GL11.glDrawElements(GL11.GL_TRIANGLES, rawModel.getVertexCount(), GL11.GL_UNSIGNED_INT, 0);
GL20.glDisableVertexAttribArray(0);
GL20.glDisableVertexAttribArray(1);
GL20.glDisableVertexAttribArray(2);
GL30.glBindVertexArray(0);
}
private void createProjectionMatrix(){
float aspectRatio = (float) Display.getWidth() / (float) Display.getHeight();
float y_scale = (float) ((1f / Math.tan(Math.toRadians(FOV / 2f))) * aspectRatio);
float x_scale = y_scale / aspectRatio;
float frustum_length = FAR_PLANE - NEAR_PLANE;
projectionMatrix = new Matrix4f();
projectionMatrix.m00 = x_scale;
projectionMatrix.m11 = y_scale;
projectionMatrix.m22 = -((FAR_PLANE + NEAR_PLANE) / frustum_length);
projectionMatrix.m23 = -1;
projectionMatrix.m32 = -((2 * NEAR_PLANE * FAR_PLANE) / frustum_length);
projectionMatrix.m33 = 0;
}
}
静态着色器类:
package shaders;
import org.lwjgl.util.vector.Matrix4f;
import toolbox.Maths;
import entities.Camera;
import entities.Light;
public class StaticShader extends ShaderProgram{
private static final String VERTEX_FILE = "src/shaders/vertexShader.txt";
private static final String FRAGMENT_FILE = "src/shaders/fragmentShader.txt";
private int location_transformationMatrix;
private int location_projectionMatrix;
private int location_viewMatrix;
private int location_lightPosition;
private int location_lightColour;
public StaticShader() {
super(VERTEX_FILE, FRAGMENT_FILE);
}
@Override
protected void bindAttributes() {
System.out.println("called");
super.bindAttribute(0, "position");
super.bindAttribute(1, "textureCoordinates");
super.bindAttribute(2, "normal");
}
@Override
protected void getAllUniformLocations() {
location_transformationMatrix = super.getUniformLocation("transformationMatrix");
location_projectionMatrix = super.getUniformLocation("projectionMatrix");
location_viewMatrix = super.getUniformLocation("viewMatrix");
location_lightPosition = super.getUniformLocation("lightPosition");
location_lightColour = super.getUniformLocation("lightColour");
}
public void loadTransformationMatrix(Matrix4f matrix){
super.loadMatrix(location_transformationMatrix, matrix);
}
public void loadLight(Light light) {
super.loadVector(location_lightPosition, light.getPosition());
super.loadVector(location_lightColour, light.getColour());
}
public void loadViewMatrix(Camera camera){
Matrix4f viewMatrix = Maths.createViewMatrix(camera);
super.loadMatrix(location_viewMatrix, viewMatrix);
}
public void loadProjectionMatrix(Matrix4f projection){
super.loadMatrix(location_projectionMatrix, projection);
}
}
ShaderProgram 类:(这是它令人讨厌的“无法编译”的地方)
package shaders;
import java.io.BufferedReader;
import java.io.FileReader;
import java.io.IOException;
import java.nio.FloatBuffer;
import org.lwjgl.BufferUtils;
import org.lwjgl.opengl.GL11;
import org.lwjgl.opengl.GL20;
import org.lwjgl.util.vector.Matrix4f;
import org.lwjgl.util.vector.Vector3f;
public abstract class ShaderProgram {
private int programID;
private int vertexShaderID;
private int fragmentShaderID;
private static FloatBuffer matrixBuffer = BufferUtils.createFloatBuffer(16);
public ShaderProgram(String vertexFile,String fragmentFile){
vertexShaderID = loadShader(vertexFile,GL20.GL_VERTEX_SHADER);
fragmentShaderID = loadShader(fragmentFile,GL20.GL_FRAGMENT_SHADER);
programID = GL20.glCreateProgram();
GL20.glAttachShader(programID, vertexShaderID);
GL20.glAttachShader(programID, fragmentShaderID);
bindAttributes();
GL20.glLinkProgram(programID);
GL20.glValidateProgram(programID);
getAllUniformLocations();
}
protected abstract void getAllUniformLocations();
protected int getUniformLocation(String uniformName){
return GL20.glGetUniformLocation(programID,uniformName);
}
public void start(){
GL20.glUseProgram(programID);
}
public void stop(){
GL20.glUseProgram(0);
}
public void cleanUp(){
stop();
GL20.glDetachShader(programID, vertexShaderID);
GL20.glDetachShader(programID, fragmentShaderID);
GL20.glDeleteShader(vertexShaderID);
GL20.glDeleteShader(fragmentShaderID);
GL20.glDeleteProgram(programID);
}
protected abstract void bindAttributes();
protected void bindAttribute(int attribute, String variableName){
GL20.glBindAttribLocation(programID, attribute, variableName);
}
protected void loadFloat(int location, float value){
GL20.glUniform1f(location, value);
}
protected void loadVector(int location, Vector3f vector){
GL20.glUniform3f(location,vector.x,vector.y,vector.z);
}
protected void loadBoolean(int location, boolean value){
float toLoad = 0;
if(value){
toLoad = 1;
}
GL20.glUniform1f(location, toLoad);
}
protected void loadMatrix(int location, Matrix4f matrix){
matrix.store(matrixBuffer);
matrixBuffer.flip();
GL20.glUniformMatrix4(location, false, matrixBuffer);
}
private static int loadShader(String file, int type){
StringBuilder shaderSource = new StringBuilder();
try{
BufferedReader reader = new BufferedReader(new FileReader(file));
String line;
while((line = reader.readLine())!=null){
shaderSource.append(line).append("//\n");
}
reader.close();
}catch(IOException e){
e.printStackTrace();
System.exit(-1);
}
int shaderID = GL20.glCreateShader(type);
GL20.glShaderSource(shaderID, shaderSource);
GL20.glCompileShader(shaderID);
if(GL20.glGetShader(shaderID, GL20.GL_COMPILE_STATUS )== GL11.GL_FALSE){
System.out.println(GL20.glGetShaderInfoLog(shaderID, 500));
System.err.println("Could not compile shader!");
System.exit(-1);
}
return shaderID;
}
}
OBJloader类:
package renderEngine;
import java.io.BufferedReader;
import java.io.File;
import java.io.FileNotFoundException;
import java.io.FileReader;
import java.util.ArrayList;
import java.util.List;
import org.lwjgl.util.vector.Vector2f;
import org.lwjgl.util.vector.Vector3f;
import models.RawModel;
public class OBJLoader {
public static RawModel loadObjModel(String fileName, Loader loader) {
FileReader fr = null;
try {
fr = new FileReader(new File("res/"+fileName+".obj"));
} catch (FileNotFoundException e) {
System.err.println("Could Not Load File!");
e.printStackTrace();
}
BufferedReader reader = new BufferedReader(fr);
String line;
List<Vector3f> vertices = new ArrayList<Vector3f>();
List<Vector2f> textures = new ArrayList<Vector2f>();
List<Vector3f> normals = new ArrayList<Vector3f>();
List<Integer> indices = new ArrayList<Integer>();
float[] verticesArray = null;
float[] normalsArray = null;
float[] textureArray = null;
int[] indicesArray = null;
try {
while(true) {
line = reader.readLine();
String[] currentLine = line.split(" ");
if(line.startsWith("v ")) {
Vector3f vertex = new Vector3f(Float.parseFloat(currentLine[1]),Float.parseFloat(currentLine[2]),Float.parseFloat(currentLine[3]));
vertices.add(vertex);
}else if(line.startsWith("vt ")) {
Vector2f texture = new Vector2f(Float.parseFloat(currentLine[1]),Float.parseFloat(currentLine[2]));
textures.add(texture);
}else if(line.startsWith("vn ")) {
Vector3f normal = new Vector3f(Float.parseFloat(currentLine[1]),Float.parseFloat(currentLine[2]),Float.parseFloat(currentLine[3]));
normals.add(normal);
}else if(line.startsWith("f ")) {
textureArray = new float[vertices.size()*2];
normalsArray = new float[vertices.size()*3];
break;
}
}
while(line!=null) {
if(!line.startsWith("f ")) {
line = reader.readLine();
continue;
}
String[] currentLine = line.split(" ");
String[] vertex1 = currentLine[1].split("/");
String[] vertex2 = currentLine[2].split("/");
String[] vertex3 = currentLine[3].split("/");
processVertex(vertex1, indices, textures, normals, textureArray, normalsArray);
processVertex(vertex2, indices, textures, normals, textureArray, normalsArray);
processVertex(vertex3, indices, textures, normals, textureArray, normalsArray);
line = reader.readLine();
}
reader.close();
}catch(Exception e){
e.printStackTrace();
}
verticesArray = new float[vertices.size()*3];
indicesArray = new int[indices.size()];
int vertexPointer = 0;
for(Vector3f vertex:vertices) {
verticesArray[vertexPointer++] = vertex.x;
verticesArray[vertexPointer++] = vertex.y;
verticesArray[vertexPointer++] = vertex.z;
}
for(int i = 0;i<indices.size();i++) {
indicesArray[i] = indices.get(i);
}
System.out.println("OBJLoader");
return loader.loadToVAO(verticesArray, textureArray, normalsArray, indicesArray);
}
private static void processVertex(String[] vertexData, List<Integer> indices, List<Vector2f> textures, List<Vector3f> normals, float[] textureArray, float[] normalsArray) {
int currentVertexPointer = Integer.parseInt(vertexData[0]) - 1;
indices.add(currentVertexPointer);
Vector2f currentTex = textures.get(Integer.parseInt(vertexData[1]) - 1);
textureArray[currentVertexPointer*2] = currentTex.x;
textureArray[currentVertexPointer*2+1] = 1 - currentTex.y;
Vector3f currentNorm = normals.get(Integer.parseInt(vertexData[2]) - 1);
normalsArray[currentVertexPointer*3] = currentNorm.x;
normalsArray[currentVertexPointer*3+1] = currentNorm.y;
normalsArray[currentVertexPointer*3+2] = currentNorm.z;
}
}
VertexShader:(.txt 文件)
#version 400 core
in vec3 position;
in vec2 textureCoordinates;
in vec3 normal;
out vec2 pass_textureCoordinates;
out vec3 surfaceNormal;
out vec3 toLightVector;
uniform mat4 transformationMatrix;
uniform mat4 projectionMatrix;
uniform mat4 viewMatrix;
uniform vec3 lightPosition;
void main(void){
vec4 worldPosition = transformationMatrix * vec4(position,1.0);
gl_Position = projectionMatrix * viewMatrix * worldPosition
pass_textureCoordinates = textureCoordinates;
surfaceNormal = (transformationMatrix * vec4(normal, 0.0)).xyz;
toLightVector = lightPosition - worldPosition.xyz;
}
fragmentShader:(也是 .txt 文件)
#version 400 core
in vec2 pass_textureCoordinates;
in vec3 surfaceNormal;
in vec3 toLightVector;
out vec4 out_Color;
uniform sampler2D modelTexture;
uniform vec3 lightColour;
void main(void){
vec3 unitNormal = normalize(surfaceNormal);
vec3 unitLightVector = normalize(toLightVector);
float nDot1 = dot(unitNormal,unitLightVector);
float brightness = max(nDot1,0.0);
vec3 diffuse = brightness * lightColour;
out_Color = vec4(diffuse,1.0) * texture(modelTexture,pass_textureCoordinates);
}