如何解决OpenGL ES 在 android 上绘制一个正方形
我尝试在 OpenGL ES 中为 android 绘制一个正方形,但由于某种原因,我的代码崩溃了,或者只显示了 clearColor。我敢肯定,使用渲染器和 GLSurfaceView 类设置的项目是正确的,并且从文件导入顶点和片段着色器的函数工作正常。这是绘制正方形的代码(在我的渲染器类的 onDrawFrame 方法中的 draw 方法的 onSurfaceCreated 中调用构造函数):
import android.content.Context;
import android.opengl.GLES20;
import java.io.BufferedReader;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.nio.FloatBuffer;
import java.nio.IntBuffer;
public class Square {
int ShaderProgramID;
private FloatBuffer vertexBuffer;
private int vertexBufferID;
private int vertexCount;
private int vertexStride;
static final int COORDS_PER_VERTEX = 3;
static final int COLORS_PER_VERTEX = 4;
static final int SIZE_OF_FLOAT = 4;
static final float coords[] = {
//x: y: z: r: g: b: a:
-0.5f,0.5f,0.0f,1.0f,-0.5f,};
public Square(Context context) {
String vertexShaderSrc = ReadFromfile("defaultVertexShader.glsl",context);
String fragmentShaderSrc = ReadFromfile("defaultFragmentShader.glsl",context);
int vertexID = GLES20.glCreateShader(GLES20.GL_VERTEX_SHADER);
GLES20.glShaderSource(vertexID,vertexShaderSrc);
GLES20.glCompileShader(vertexID);
int fragmetID = GLES20.glCreateShader(GLES20.GL_FRAGMENT_SHADER);
GLES20.glShaderSource(fragmetID,fragmentShaderSrc);
GLES20.glCompileShader(fragmetID);
ShaderProgramID = GLES20.glCreateProgram();
GLES20.glAttachShader(ShaderProgramID,vertexID);
GLES20.glAttachShader(ShaderProgramID,fragmetID);
GLES20.glBindAttribLocation(ShaderProgramID,"aPos");
GLES20.glBindAttribLocation(ShaderProgramID,1,"aColor");
GLES20.glLinkProgram(ShaderProgramID);
positionHandle = GLES20.glGetAttribLocation(ShaderProgramID,"a_Position");
colorHandle = GLES20.glGetAttribLocation(ShaderProgramID,"a_Color");
vertexBuffer = FloatBuffer.allocate(coords.length);
vertexBuffer.put(coords);
vertexBuffer.position(0);
IntBuffer buffer = IntBuffer.allocate(1);
GLES20.glGenBuffers(1,buffer);
vertexBufferID = buffer.get(0);
GLES20.glBindBuffer(GLES20.GL_ARRAY_BUFFER,vertexBufferID);
GLES20.glBufferData(GLES20.GL_ARRAY_BUFFER,coords.length * 4,vertexBuffer,GLES20.GL_STATIC_DRAW);
vertexCount = coords.length / (COORDS_PER_VERTEX + COLORS_PER_VERTEX);
vertexStride = (COORDS_PER_VERTEX + COLORS_PER_VERTEX) * 4;
}
private int positionHandle;
private int colorHandle;
public void draw() {
GLES20.gluseProgram(ShaderProgramID);
vertexBuffer.position(0);
GLES20.glVertexAttribPointer(positionHandle,COORDS_PER_VERTEX,GLES20.GL_FLOAT,false,vertexStride,vertexBuffer);
GLES20.glEnabLevertexAttribArray(positionHandle);
vertexBuffer.position(3);
GLES20.glVertexAttribPointer(colorHandle,COLORS_PER_VERTEX,vertexBuffer);
GLES20.glEnabLevertexAttribArray(colorHandle);
GLES20.glDrawArrays(GLES20.GL_TRIANGLES,6);
GLES20.gldisabLevertexAttribArray(positionHandle);
GLES20.gldisabLevertexAttribArray(colorHandle);
}
public String ReadFromfile(String fileName,Context context) {
StringBuilder ReturnString = new StringBuilder();
InputStream fIn = null;
InputStreamReader isr = null;
BufferedReader input = null;
try {
fIn = context.getResources().getAssets()
.open(fileName);
isr = new InputStreamReader(fIn);
input = new BufferedReader(isr);
String line = "";
while ((line = input.readLine()) != null) {
ReturnString.append(line + "\n");
}
} catch (Exception e) {
e.getMessage();
} finally {
try {
if (isr != null)
isr.close();
if (fIn != null)
fIn.close();
if (input != null)
input.close();
} catch (Exception e2) {
e2.getMessage();
}
}
return ReturnString.toString();
}
}
这是顶点着色器代码:
attribute vec4 aPos;
attribute vec4 aColor;
varying vec4 v_Color;
void main()
{
v_Color = a_Color;
gl_Position = a_Position;
}
这是 Fragmentshadercode
precision mediump float;
varying vec4 v_Color;
void main()
{
gl_FragColor = v_Color;
}
解决方法
在顶点着色器中:
attribute vec4 aPos;
position 是 4 分量向量,但在“vertexBuffer”中位置被写为 3 分量向量。所以尝试改进着色器:
attribute vec3 aPos;
还使用了“a_Position”,但未在任何地方声明,请执行以下操作:
gl_Position = vec4(a_Pos,1.0);
并在此处改进:
positionHandle = GLES20.glGetAttribLocation(ShaderProgramID,"a_Pos");
此代码可以显示着色器是否已编译,以及一个错误。
int[] compiled = new int[1];
GLES31.glGetShaderiv(shader,GLES31.GL_COMPILE_STATUS,compiled,0);
if (compiled[0] == 0) {
GLES31.glDeleteShader(shader);
throw new RuntimeException("Could not compile program: "
+ GLES31.glGetShaderInfoLog(shader) + " | ");
}
这是准备浮动缓冲区的正确方法:
ByteBuffer bb = ByteBuffer.allocateDirect(coords.length*4);
bb.order(ByteOrder.nativeOrder());
FloatBuffer vertexBuffer = bb.asFloatBuffer();
,
这是当前代码:
import android.content.Context;
import android.opengl.GLES20;
import android.opengl.GLES31;
import android.util.Log;
import java.io.BufferedReader;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.nio.FloatBuffer;
import java.nio.IntBuffer;
public class Square {
int ShaderProgramID;
private FloatBuffer vertexBuffer;
private int vertexBufferID;
private int vertexCount;
private int vertexStride;
static final int COORDS_PER_VERTEX = 3;
static final int COLORS_PER_VERTEX = 4;
static final int SIZE_OF_FLOAT = 4;
static final float coords[] = {
//x: y: z: r: g: b: a:
-0.5f,0.5f,0.0f,1.0f,-0.5f,};
public Square(Context context) {
String vertexShaderSrc = ReadFromfile("defaultVertexShader.glsl",context);
String fragmentShaderSrc = ReadFromfile("defaultFragmentShader.glsl",context);
int vertexID = GLES20.glCreateShader(GLES20.GL_VERTEX_SHADER);
GLES20.glShaderSource(vertexID,vertexShaderSrc);
GLES20.glCompileShader(vertexID);
int fragmetID = GLES20.glCreateShader(GLES20.GL_FRAGMENT_SHADER);
GLES20.glShaderSource(fragmetID,fragmentShaderSrc);
GLES20.glCompileShader(fragmetID);
ShaderProgramID = GLES20.glCreateProgram();
GLES20.glAttachShader(ShaderProgramID,vertexID);
GLES20.glAttachShader(ShaderProgramID,fragmetID);
GLES20.glBindAttribLocation(ShaderProgramID,"aPos");
GLES20.glBindAttribLocation(ShaderProgramID,1,"aColor");
GLES20.glLinkProgram(ShaderProgramID);
positionHandle = GLES20.glGetAttribLocation(ShaderProgramID,"aPos");
colorHandle = GLES20.glGetAttribLocation(ShaderProgramID,"aColor");
vertexBuffer = FloatBuffer.allocate(coords.length);
vertexBuffer.put(coords);
vertexBuffer.position(0);
IntBuffer buffer = IntBuffer.allocate(1);
GLES20.glGenBuffers(1,buffer);
vertexBufferID = buffer.get(0);
GLES20.glBindBuffer(GLES20.GL_ARRAY_BUFFER,vertexBufferID);
GLES20.glBufferData(GLES20.GL_ARRAY_BUFFER,coords.length * 4,vertexBuffer,GLES20.GL_STATIC_DRAW);
vertexCount = coords.length / (COORDS_PER_VERTEX + COLORS_PER_VERTEX);
vertexStride = (COORDS_PER_VERTEX + COLORS_PER_VERTEX) * 4;
}
private int positionHandle;
private int colorHandle;
public void draw() {
GLES20.glUseProgram(ShaderProgramID);
vertexBuffer.position(0);
GLES20.glVertexAttribPointer(positionHandle,COORDS_PER_VERTEX,GLES20.GL_FLOAT,false,vertexStride,0);
GLES20.glEnableVertexAttribArray(positionHandle);
vertexBuffer.position(3);
GLES20.glVertexAttribPointer(colorHandle,COLORS_PER_VERTEX,3);
GLES20.glEnableVertexAttribArray(colorHandle);
GLES20.glDrawArrays(GLES20.GL_TRIANGLES,6);
GLES20.glDisableVertexAttribArray(positionHandle);
GLES20.glDisableVertexAttribArray(colorHandle);
}
public String ReadFromfile(String fileName,Context context) {
StringBuilder ReturnString = new StringBuilder();
InputStream fIn = null;
InputStreamReader isr = null;
BufferedReader input = null;
try {
fIn = context.getResources().getAssets()
.open(fileName);
isr = new InputStreamReader(fIn);
input = new BufferedReader(isr);
String line = "";
while ((line = input.readLine()) != null) {
ReturnString.append(line + "\n");
}
} catch (Exception e) {
e.getMessage();
} finally {
try {
if (isr != null)
isr.close();
if (fIn != null)
fIn.close();
if (input != null)
input.close();
} catch (Exception e2) {
e2.getMessage();
}
}
return ReturnString.toString();
}
}
片段:
#version 310 es
precision mediump float;
in vec4 vColor;
void main()
{
gl_FragColor = vColor;
}
顶点:
#version 310 es
attribute vec3 aPos;
attribute vec4 aColor;
out vec4 vColor;
void main()
{
vColor = aColor;
gl_Position = vec4(aPos,1.0);
}
版权声明:本文内容由互联网用户自发贡献,该文观点与技术仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 dio@foxmail.com 举报,一经查实,本站将立刻删除。