我正在尝试使用着色器(感兴趣的点是负责输出最终顶点位置的顶点着色器)正确地平移网格点并将其投影到窗口表面。
模型(四边形)由以下顶点表示:[-0.5f,0.5f,0f](V0),[-0.5f,-0.5f,0f](V1),[0.5f,-0.5f,0f](V2),[0.5f,0.5f,0]。
我有以下两种方法来创建透视投影矩阵:
public static Matrix4f getProjectionMatrix(float fovy, int width, int height, float zNear, float zFar) {
float aspectRatio = (float) width / height;
projectionMatrix.perspective(fovy, aspectRatio, zNear, zFar);
return projectionMatrix;
}
这个方法可以在Transformations类中找到,它创建并返回透视投影矩阵。
>
fovy=垂直视野
宽度=窗口的宽度
高度=窗户的高度
zNear=近剪裁平面
zFar=远剪裁平面
public Matrix4f perspective(float fovy, float aspectRatio, float zNear, float zFar) {
float scale = (float) (Math.tan(fovy * 0.5) * zNear);
float top = scale;
float right = top * aspectRatio;
float bottom = -top;
float left = bottom * aspectRatio;
this.m00 = 2*zNear / (right - left);
this.m03 = (right + left) / (right - left);
this.m11 = 2*zNear / (top - bottom);
this.m12 = (top + bottom) / (top - bottom);
this.m22 = -(zFar + zNear) / (zFar - zNear);
this.m23 = -2*zFar*zNear / (zFar - zNear);
this.m32 = -1;
return this;
}此方法位于Matrix4f类中。
下面是Matrix4f类的开头,其中包含Matrix4f实例变量和构造函数:
public class Matrix4f {
float m00, m01, m02, m03;
float m10, m11, m12, m13;
float m20, m21, m22, m23;
float m30, m31, m32, m33;
public Matrix4f() {
m00 = 1.0f; m01 = 0.0f; m02 = 0.0f; m03 = 0.0f;
m10 = 0.0f; m11 = 1.0f; m12 = 0.0f; m13 = 0.0f;
m20 = 0.0f; m21 = 0.0f; m22 = 1.0f; m23 = 0.0f;
m30 = 0.0f; m31 = 0.0f; m32 = 0.0f; m33 = 1.0f;
}
调用构造函数后,就已经创建了标识矩阵。剩下的就是知道如何初始化透视投影矩阵。这是在调用类转换的构造函数时完成的:
public class Transformations {
private Matrix4f translationMatrix;
private static Matrix4f projectionMatrix;
public Transformations() {
translationMatrix = new Matrix4f();
projectionMatrix = new Matrix4f();
}
现在来看翻译矩阵。Transformations类通过方法getTranslationMatrix(float x,float y,float z)
提供了创建它的功能,该方法使用以下参数创建并返回一个转换矩阵:
public Matrix4f getTranslationMatrix(float x, float y, float z) {
translationMatrix.m03 = x;
translationMatrix.m13 = y;
translationMatrix.m23 = z;
return translationMatrix;
}
为了实际拥有代表游戏模型的东西,我创建了一个名为GameEntity的类。它表示模型的网格和位置:
public class GameEntity {
private final Mesh mesh;
private Vector3f position;
public GameEntity(Mesh mesh) {
this.mesh = mesh;
position = new Vector3f(0, 0, 0);
}
public Vector3f getPosition() {
return position;
}
public void updatePosition(float x, float y, float z) {
position.x += x;
position.y += y;
position.z += z;
}
public Mesh getMesh() {
return mesh;
}
}
updatePosition
方法应该将实体作为一个整体在窗口周围移动。我不会在这里包括Mesh类的代码解释。你需要知道的是,它保存了关于游戏实体的网格(顶点)数据,例如顶点位置、顶点颜色、索引等,这些数据都存储在顶点数组对象中,然后用于将网格实例渲染到窗口中。在我的例子中,两个三角形组成一个四边形,它们被表示为一个GameEntity实例。
移动模型:每次按下W、A、S、D、space或left shift键时,都会调用updatePosition方法。它会将GameEntity实例(存储在索引0处的GameEntity[]entities
数组中)的位置更新一个设置的数量:
private void processInput() {
glfwPollEvents();
if (window.keys[GLFW_KEY_W]) {
entities[0].updatePosition(0, 0, -1.0f);
} else if (window.keys[GLFW_KEY_S]){
entities[0].updatePosition(0, 0, 1.0f);
} else if (window.keys[GLFW_KEY_A]) {
entities[0].updatePosition(1.0f, 0, 0);
} else if (window.keys[GLFW_KEY_D]) {
entities[0].updatePosition(-1.0f, 0, 0);
} else if (window.keys[GLFW_KEY_SPACE]) {
entities[0].updatePosition(0, 1.0f, 0);
} else if (window.keys[GLFW_KEY_LEFT_SHIFT]) {
entities[0].updatePosition(0, -1.0f, 0);
}
}
此方法在主游戏循环中调用。
然后,在Renderer类中,根据模型的位置构造模型的平移矩阵,并根据窗口对象的属性构造投影矩阵:
private ShaderProgram shaderProgram;
private Window window = new Window();
private final Transformations transformation;
private Matrix4f translationMatrix = new Matrix4f();
private Matrix4f projectionMatrix = new Matrix4f();
private static double angleOfView = 60.0;
private static final float FOVY = (float) Math.toRadians(angleOfView);
private static final float zNear = 0.01f;
private static final float zFar = 1000.0f;
shaderProgram.createUniform("translationMatrix");
shaderProgram.createUniform("projectionMatrix");
public void render(Window window, GameEntity[] entities) {
i++;
clear();
if (window.isResized()) {
glViewport(0, 0, window.getWidth(), window.getHeight());
window.setResized(false);
}
//make the shaders active
shaderProgram.bind();
//update the projection matrix
Matrix4f projectionMatrix = transformation.getProjectionMatrix(FOVY, window.getWidth(), window.getHeight(), zNear, zFar);
shaderProgram.setUniformMatrix("projectionMatrix", projectionMatrix);
//render each game item
for(GameEntity entity : entities) {
Matrix4f translationMat = transformation.getTranslationMatrix(entity.getPosition());
shaderProgram.setUniformMatrix("translationMatrix", translationMat);
entity.getMesh().render();
}
shaderProgram.unbind();
}
首先,定义所有的统一位置(在渲染()
方法上面)。
clear()
方法清除渲染缓冲区——它为渲染新图像做好准备。在下面的if子句中,处理窗口大小调整操作。如果调整了窗口的大小,则带有相应方法的If子句将更新窗口的宽度
和高度
,以匹配调整大小的窗口。
projectionMatrix
由定义为渲染器类实例变量的变量(FOVY
,zNear
,zFar
)和两个获取窗口对象当前宽度和高度的变量(window.getWidth()
,window)构成。getHeight()
)。
然后,通过调用shaderProgram将投影矩阵“发送”到顶点着色器。setUniformMatrix(“projectionMatrix”,projectionMatrix)
:
private final Map<String, Integer> uniforms;
public void createUniform(String uniformName) throws Exception {
int uniformLocation = glGetUniformLocation(programID, uniformName);
if (uniformLocation < 0) {
throw new Exception("[ShaderProgram.createUniform]: Couldn't find uniform: " + uniformName);
}
uniforms.put(uniformName, uniformLocation);
}
此方法位于ShaderProgram类中,该类保存对活动着色器porgram的引用以及与之关联的统一变量,这些变量存储在Hashmap中。
然后,在for循环中,渲染两个四边形。首先,基于GameInstance的位置值构建一个转换矩阵,该位置值表示为三元组向量(x,y,z)。然后,创建的矩阵被“发送”到顶点着色器。
现在,将透视投影(
投影矩阵
)和平移矩阵(平移矩阵
x)发送到顶点着色器后,是时候调用我们的Mesh实例上的渲染方法来渲染它了。渲染()方法的代码(在entity.getMesh()的上下文中)。渲染()
)是:
public void render() {
glBindVertexArray(getVaoID());
glEnableVertexAttribArray(0);
glEnableVertexAttribArray(1);
glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, getIndicesVboID());
glDrawElements(GL_TRIANGLES, getVertexCount(), GL_UNSIGNED_INT, 0);
glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, 0);
glDisableVertexAttribArray(0);
glBindVertexArray(0);
}
然而,结果并不令人满意。按下W或S时,四边形(两个三角形)会离“我们”更远或更近,这是正确的。但是,当按下A或D时(应该在x轴上平移模型),四边形(两个三角形)不会平移。它只是绕着中心旋转。如何解决这个问题?
似乎行/列命名法有问题。
据我所知,矩阵中你的代码单元格mij
是coll=i,row=j
OpenGL需要16个值的数组,即13、14、15个位置的平移。通常这被称为“列主顺序”,翻译在第四列。
所以试试这个:
public Matrix4f getTranslationMatrix(float x, float y, float z) {
translationMatrix.m30 = x;
translationMatrix.m31 = y;
translationMatrix.m32 = z;
return translationMatrix;
}
另外,回顾一下你的视角
。我想你在ij
索引中有一些错误<代码>ii单元格看起来不错。
我正在尝试使用ajax php和jquery上传图像,我在这里做错了什么。应在不刷新页面的情况下上载图像。我试过上面的代码。如果你看到任何问题,请帮忙!! 问题是我想将上传的文件移动到上传文件夹并将图像名称作为BLOB插入数据库。
我是MVVMCROSS6.0和Xamarin的新手。 null ConfigurationChanges=ConfigChanges.Screensize ConfigChanges.Orientation)]公共类MainActivity:MvxFormsAppCompatActivity{protected override void OnCreate(Bundle Bundle){TabLa
我正在做一个项目,我的意图是运行一个玉米作业,并发送邮件给我的朋友,祝他们生日,我能够从MySQL DB获取电子邮件,并将其与当前日期进行比较,但当涉及到发送电子邮件时,我得到NullPointerException。 我确信应用程序属性没有问题,我在其他项目中也使用了它们,它们的功能正常 这是我得到以下信息的错误
我正试图将即时消息添加到现有的应用程序中。但是我不确定应该如何配置socket.io模块。我已经尝试了以下方法: 因为打开一个页面时没有记录connected,所以我假设丢失了一些东西。我的错误在哪里?
所以我只想使用谷歌云视觉应用编程接口从图像中检测文本或标签。但是当我运行这段代码时,我总是得到: 但我不知道为什么。。。下面是我得到的完整json输出: 我的测试代码如下: 所以问题是。。此代码有什么问题?
它返回几个错误,其中大多数显示:<代码> 我对编码很陌生,我只是想用推特API制作一个有趣的机器人,但有很多错误,我不知道该怎么办。 出现的主要错误如下: (从集合导入namedtuple,映射导入错误:无法从“集合”导入名称“映射”) 谁能帮帮我吗? 出现的错误:回溯(最近一次调用):文件“C:\Users\wgama\PycharmProjects\botesquilo\botesquilo.