如果我传递一个包含3个浮点数的浮点数组,则表示没有W组件的顶点的XYZ,我将它传递给VBO,并告诉我的着色器中的输入变量使用的内容VBO但这个输入变量是vec4类型,着色器是否将w组件设置为1?此外,顶点是否会被着色器标准化?
MainDisplay类:
package com.dryadengine.gui;
import com.dryadengine.core.Model;
import com.dryadengine.framework.OBJLoader;
import com.dryadengine.framework.ShaderFactory;
import java.io.File;
import java.io.FileNotFoundException;
import java.io.IOException;
import java.nio.FloatBuffer;
import java.util.logging.Level;
import java.util.logging.Logger;
import org.lwjgl.LWJGLException;
import org.lwjgl.BufferUtils;
import org.lwjgl.opengl.Display;
import org.lwjgl.opengl.DisplayMode;
import static org.lwjgl.opengl.GL11.*;
import static org.lwjgl.opengl.GL15.*;
import static org.lwjgl.opengl.GL20.*;
import org.lwjgl.util.vector.Matrix4f;
/**
*
* @author Roy
*/
public class MainDisplay {
private Model bunny;
private FloatBuffer vbo;
private Matrix4f mProjection;
private Matrix4f mView;
private Matrix4f mModel;
private int shaderProgramID;
private int vboID;
private int vPositionID;
private int mProjectionID;
private int mViewID;
private int mModelID;
/**
* @param args the command line arguments
*/
public static void main(String[] args) {
MainDisplay md = new MainDisplay();
md.create();
md.init();
md.run();
}
public MainDisplay() {
}
public void create() {
try {
Display.setDisplayMode(new DisplayMode(800, 600));
Display.setTitle("Dryad Engine 1.0.0");
Display.setFullscreen(false);
Display.setResizable(true);
Display.create();
} catch (LWJGLException ex) {
Logger.getLogger(MainDisplay.class.getName()).log(Level.SEVERE, null, ex);
System.exit(-1);
}
}
public void init() {
glClearColor(0.0f, 0.0f, 0.0f, 1.0f);
try {
shaderProgramID = ShaderFactory.createShaderProgram("vertexShader", "fragmentShader");
glUseProgram(shaderProgramID);
bunny = OBJLoader.parseOBJ(new File("src/com/dryadengine/assets/bunny.obj"));
vbo = BufferUtils.createFloatBuffer(bunny.getFaces().size() * 3 * 3);
float[] vertexData = new float[bunny.getFaces().size() * 3 * 3];
// System.out.println("PRINTING 10 first faces info : ");
// for (int i = 0; i < 10; i++) {
// System.out.println("FACE #" +(i+1));
// for (int j = 0; j < 3; j++) {
// System.out.println("VERTEX #" +(j + 1));
// System.out.println(bunny.getFaces().get(i).getVertices()[j].x + ", " +bunny.getFaces().get(i).getVertices()[j].y+ ", " +bunny.getFaces().get(i).getVertices()[j].z);
// }
// }
for (int i = 0; i < bunny.getFaces().size(); i++) {
for (int j = 0; j < 3; j++) {
//System.out.println("placing new vertex at cell #" +((i * 3 + j) * 3));
vertexData[(i * 3 + j) * 3] = bunny.getFaces().get(i).getVertices()[j].x;
//System.out.println("placing new vertex at cell #" +((i * 3 + j) * 3 + 1));
vertexData[(i * 3 + j) * 3 + 1] = bunny.getFaces().get(i).getVertices()[j].y;
//System.out.println("placing new vertex at cell #" +((i * 3 + j) * 3 + 2));
vertexData[(i * 3 + j) * 3 + 2] = bunny.getFaces().get(i).getVertices()[j].z;
}
}
vbo.put(vertexData);
vbo.flip();
vboID = glGenBuffers();
glBindBuffer(GL_ARRAY_BUFFER, vboID);
glBufferData(GL_ARRAY_BUFFER, vbo, GL_STATIC_DRAW);
vPositionID = glGetAttribLocation(shaderProgramID, "vPosition");
glEnableVertexAttribArray(vPositionID);
mProjection = new Matrix4f();
float fieldOfView = 60f;
float aspectRatio = (float)Display.getWidth() / (float)Display.getHeight();
float nearPlane = 0.1f;
float farPlane = 100f;
float yScale = (float)(1.0f / Math.tan((fieldOfView / 2.0f) * (float)(Math.PI / 180d)));
float xScale = yScale / aspectRatio;
float frustum_length = farPlane - nearPlane;
mProjection.m00 = xScale;
mProjection.m11 = yScale;
mProjection.m22 = -((farPlane + nearPlane) / frustum_length);
mProjection.m23 = -1;
mProjection.m32 = -((2 * nearPlane * farPlane) / frustum_length);
mProjection.m33 = 0;
mView = new Matrix4f();
mView.m23 = -5;
mModel = new Matrix4f();
mProjectionID = glGetUniformLocation(shaderProgramID, "mProjection");
mViewID = glGetUniformLocation(shaderProgramID, "mView");
mModelID = glGetUniformLocation(shaderProgramID, "mModel");
glEnable(GL_CULL_FACE);
glCullFace(GL_BACK);
glEnable(GL_DEPTH_TEST);
} catch (FileNotFoundException ex) {
Logger.getLogger(MainDisplay.class.getName()).log(Level.SEVERE, null, ex);
} catch (IOException ex) {
Logger.getLogger(MainDisplay.class.getName()).log(Level.SEVERE, null, ex);
}
}
public void run() {
int fps = 0;
long lastCheck = System.nanoTime();
while (!Display.isCloseRequested()) {
if (Display.isVisible()) {
render();
}
if (Display.wasResized()) {
resize(Display.getWidth(), Display.getHeight());
}
if (System.nanoTime() - lastCheck >= 1000000000) {
System.out.println("FPS : " +fps);
fps = 0;
lastCheck = System.nanoTime();
}
fps++;
Display.update();
Display.sync(60);
}
destroy();
}
public void render() {
glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
FloatBuffer fb1 = BufferUtils.createFloatBuffer(16);
FloatBuffer fb2 = BufferUtils.createFloatBuffer(16);
FloatBuffer fb3 = BufferUtils.createFloatBuffer(16);
mProjection.store(fb1);
mView.store(fb2);
mModel.store(fb3);
fb1.flip();
fb2.flip();
fb3.flip();
glUniformMatrix4(mProjectionID, false, fb1);
glUniformMatrix4(mViewID, false, fb2);
glUniformMatrix4(mModelID, false, fb3);
glVertexAttribPointer (vPositionID, 3, GL_FLOAT, false, 0, 0);
glDrawArrays(GL_TRIANGLES, 0, bunny.getFaces().size() * 3);
}
public void resize(int width, int height) {
glViewport(0, 0, width, height);
}
public void dispose() {
glDeleteProgram(shaderProgramID);
glUseProgram(0);
glDeleteBuffers(vboID);
glBindBuffer(GL_ARRAY_BUFFER, 0);
}
public void destroy() {
dispose();
Display.destroy();
}
}
ShaderFactory类:
package com.dryadengine.framework;
import java.io.BufferedReader;
import java.io.FileNotFoundException;
import java.io.IOException;
import java.io.InputStreamReader;
import java.util.ArrayList;
import static org.lwjgl.opengl.GL11.*;
import static org.lwjgl.opengl.GL20.*;
/**
*
* @author Roy
*/
public class ShaderFactory {
private static final String COMMON_SHADERS_PATH = "/com/dryadengine/shaders/";
private static final String SHADER_EXTENSION = ".dsf";
/**
*
* @param vertexShaderName
* @param fragmentShaderName
* @return a shader program
* @throws FileNotFoundException
* @throws IOException
*/
public static int createShaderProgram(String vertexShaderName, String fragmentShaderName) throws FileNotFoundException, IOException {
ArrayList<Integer> shaders = new ArrayList();
shaders.add(ShaderFactory.compileShader(GL_VERTEX_SHADER, getShaderFileCode(COMMON_SHADERS_PATH + vertexShaderName + SHADER_EXTENSION)));
shaders.add(ShaderFactory.compileShader(GL_FRAGMENT_SHADER, getShaderFileCode(COMMON_SHADERS_PATH + fragmentShaderName + SHADER_EXTENSION)));
return ShaderFactory.linkProgram(shaders);
}
/**
*
* @param shaderFilePath
* @return a shader file code
* @throws FileNotFoundException
* @throws IOException
*/
private static String getShaderFileCode(String shaderFilePath) throws FileNotFoundException, IOException {
StringBuilder shaderCode = new StringBuilder();
String line;
try {
try (BufferedReader br = new BufferedReader(new InputStreamReader(ShaderFactory.class.getResourceAsStream(shaderFilePath)))) {
while ((line = br.readLine()) != null) {
shaderCode.append(line).append("\n");
}
}
} catch (FileNotFoundException e) {
throw new FileNotFoundException(e.getMessage());
}
return shaderCode.toString();
}
/**
*
* @param shaderType
* @param shaderCode
* @return a compiled shader file id
*/
public static int compileShader(int shaderType, String shaderCode) {
int shaderID = glCreateShader(shaderType);
glShaderSource(shaderID, shaderCode);
glCompileShader(shaderID);
int status = glGetShaderi(shaderID, GL_COMPILE_STATUS);
if (status == GL_FALSE) {
glDeleteShader(shaderID);
throw new RuntimeException(glGetShaderInfoLog(shaderID, glGetShaderi(shaderID, GL_INFO_LOG_LENGTH)));
}
return shaderID;
}
/**
* Link the vertex shader and the fragment shader to the shader program
* @param shaders
* @return a shader program
*/
public static int linkProgram(ArrayList <Integer> shaders) {
int shaderProgramID = glCreateProgram();
for (Integer shader : shaders) {
glAttachShader(shaderProgramID, shader);
}
glLinkProgram(shaderProgramID);
int status = glGetProgrami(shaderProgramID, GL_LINK_STATUS);
if (status == GL_FALSE) {
glDeleteProgram(shaderProgramID);
throw new RuntimeException(glGetShaderInfoLog(shaderProgramID, glGetProgrami(shaderProgramID, GL_INFO_LOG_LENGTH)));
}
for (int shader : shaders) {
glDeleteShader(shader);
}
return shaderProgramID;
}
}
OBJLoader类:
package com.dryadengine.framework;
import com.dryadengine.core.Face;
import com.dryadengine.core.Model;
import java.io.BufferedReader;
import java.io.File;
import java.io.FileNotFoundException;
import java.io.FileReader;
import java.io.IOException;
import java.util.ArrayList;
import java.util.List;
import org.lwjgl.util.vector.Vector3f;
/**
*
* @author Roy
*/
public class OBJLoader {
/**
* Parse .obj file and make a model from it.
* @param f
* @return a model object
* @throws FileNotFoundException
* @throws IOException
*/
public static Model parseOBJ(File f) throws FileNotFoundException, IOException {
BufferedReader br = new BufferedReader(new FileReader(f));
String line;
Model m;
List<Vector3f> vertices = new ArrayList<>();
List<Vector3f> normals = new ArrayList<>();
List<Face> faces = new ArrayList<>();
while ((line = br.readLine()) != null) {
if (line.startsWith("v ")) {
float x = Float.valueOf(line.split(" ")[1]);
float y = Float.valueOf(line.split(" ")[2]);
float z = Float.valueOf(line.split(" ")[3]);
vertices.add(new Vector3f(x, y, z));
} else if (line.startsWith("vn ")) {
float x = Float.valueOf(line.split(" ")[1]);
float y = Float.valueOf(line.split(" ")[2]);
float z = Float.valueOf(line.split(" ")[3]);
normals.add(new Vector3f(x, y, z));
} else if (line.startsWith("f ")) {
Vector3f[] a = new Vector3f[3];
Vector3f[] b = new Vector3f[3];
a[0] = vertices.get(Integer.valueOf(line.split(" ")[1].split("//")[0]) - 1);
a[1] = vertices.get(Integer.valueOf(line.split(" ")[2].split("//")[0]) - 1);
a[2] = vertices.get(Integer.valueOf(line.split(" ")[3].split("//")[0]) - 1);
b[0] = normals.get(Integer.valueOf(line.split(" ")[1].split("//")[1]) - 1);
b[1] = normals.get(Integer.valueOf(line.split(" ")[2].split("//")[1]) - 1);
b[2] = normals.get(Integer.valueOf(line.split(" ")[3].split("//")[1]) - 1);
faces.add(new Face(a, b));
}
}
br.close();
m = new Model(faces);
return m;
}
}
模特课:
package com.dryadengine.core;
import java.util.List;
/**
*
* @author Roy
*/
public class Model {
private List<Face> faces;
/**
* Construct a new model object.
* @param faces
*/
public Model(List<Face> faces) {
this.faces = faces;
}
/**
*
* @return the faces list
*/
public List<Face> getFaces() {
return faces;
}
}
面子课:
package com.dryadengine.core;
import org.lwjgl.util.vector.Vector3f;
/**
*
* @author Roy
*/
public class Face {
private Vector3f[] vertices;
private Vector3f[] normals;
public Face() {
vertices = new Vector3f[3];
normals = new Vector3f[3];
}
public Face(Vector3f[] vertices, Vector3f[] normals) {
this();
this.vertices = vertices;
this.normals = normals;
}
/**
*
* @return the vertices array
*/
public Vector3f[] getVertices() {
return vertices;
}
/**
*
* @return the normals array
*/
public Vector3f[] getNormals() {
return normals;
}
/**
* Sets the vertices array
* @param vertices
*/
public void setVertices(Vector3f[] vertices) {
this.vertices = vertices;
}
/**
* Sets the normals array
* @param normals
*/
public void setNormals(Vector3f[] normals) {
this.normals = normals;
}
}
顶点着色器:
#version 330
uniform mat4 mProjection;
uniform mat4 mView;
uniform mat4 mModel;
in vec4 vPosition;
void main()
{
gl_Position = mProjection * mView * mModel * vPosition;
}
片段着色器:
#version 330
out vec4 vOutputColor;
void main()
{
vOutputColor = vec4(1.0, 1.0, 1.0, 1.0);
}
我使用的bunny.obj文件: http://rghost.net/54750078
答案 0 :(得分:1)
是的,w
在这种情况下将是1.0。从OpenGL 3.3规范中的第2.8.1节(传输数组元素)的第一段开始:
如果size为1,那么属性的x分量由数组指定; y,z和w分量分别隐式设置为0,0和1。如果size为2,那么属性的x和y分量由数组指定; z和w分量分别隐式设置为0和1。如果size为3,则指定x,y和z,并将w隐式设置为1.如果size为4,则指定所有组件。
查看您发布的代码,我发现了将顶点坐标复制到vertexData
的问题:
vertexData[i * 3 + j] = bunny.getFaces().get(i).getVertices()[j].x;
vertexData[i * 3 + j] = bunny.getFaces().get(i).getVertices()[j].y;
vertexData[i * 3 + j] = bunny.getFaces().get(i).getVertices()[j].z;
这会将x,y和z坐标复制到同一个阵列位置。它看起来应该是这样的:
vertexData[(i * 3 + j) * 3 ] = bunny.getFaces().get(i).getVertices()[j].x;
vertexData[(i * 3 + j) * 3 + 1] = bunny.getFaces().get(i).getVertices()[j].y;
vertexData[(i * 3 + j) * 3 + 2] = bunny.getFaces().get(i).getVertices()[j].z;
编辑:我想我发现了另外一个问题。在研究了LWJGL之后,看起来矩阵的翻译部分会进入m30
,m31
,m32
。所以我相信你需要为你的模型矩阵改变这个:
mView.m23 = -5;
到此:
mView.m32 = -5;