Я пытаюсь реализовать ModelViewer, который может визуализировать триангулированные формы с реалистичным освещением.
Поскольку реалистичное освещение не представляется возможным в OpenGL ES 1.0, и мне нужен способ представить глубину для одного цветного объекта, в проекте используется OpenGL ES 2.0, который является новым для меня.
Сам объект состоит из треугольников, которые нарисованы с использованием:
GLES20.glDrawArrays(GLES20.GL_TRIANGLES, 0, vertexCount);
Что касается тестового проекта, я установил простые шейдеры, которые рисуют объект с учетом матрицы модель-вид-проекция. После этого я собирался реализовать освещение, но я не могу пройти первые шаги.
При работе с переменными переменными атрибуты вершин не будут найдены.
Удаление различных атрибутов работает, но мне нужно передать данные. Я искал несколько дней, как реализовать вершинные и фрагментные шейдеры, которые делают больше, чем просто представляют объект в определенном месте.
// VERTEX SHADER CODE
attribute vec4 v_Position;
uniform mat4 u_MVPMatrix;
uniform vec4 u_Color;
varying vec4 v_Color;
void main() {
gl_Position = u_MVPMatrix * v_Position;
v_Color = u_Color;
};
// FRAGMENT SHADER CODE
precision mediump float;
varying vec4 v_Color;
void main() {
gl_FragColor = v_Color;
}
Весь класс:
public class Object3D {
private FloatBuffer vertexBuffer;
// number of coordinates per vertex in this array
static final int COORDS_PER_VERTEX = 3;
// static float triangleCoords[] = { // in counterclockwise order:
// 0.0f, 0.622008459f, 0.0f, // top
// -0.5f, -0.311004243f, 0.0f, // bottom left
// 0.5f, -0.311004243f, 0.0f // bottom right
// };
float[] triangleCoords;
// Set color with red, green, blue and alpha (opacity) values
float[] colors = { 0.63671875f, 0.76953125f, 0.22265625f, 1.0f };
private final String vertexShaderCode =
"attribute vec4 v_Position;" +
"uniform float u_Color" +
"uniform mat4 u_MVPMatrix;" +
// outgoing
"varying vec4 v_Color" +
"void main() {" +
// the matrix must be included as a modifier of gl_Position
// Note that the uMVPMatrix factor *must be first* in order
// for the matrix multiplication product to be correct.
"gl_Position = u_MVPMatrix * v_Position;" +
"v_Color = u_Color;" +
"}";
private final String fragmentShaderCode =
"precision mediump float;" +
"varying vec4 v_Color;" +
"void main() {" +
"gl_FragColor = v_Color;" +
"}";
// Use to access and set the view transformation
private int mMVPMatrixHandle;
private final int mProgram;
private int mPositionHandle;
private int mColorHandle;
private final int vertexCount;
private final int vertexStride;
public Object3D(float[] triangleCoords) {
this.triangleCoords = triangleCoords;
vertexCount = triangleCoords.length / COORDS_PER_VERTEX;
vertexStride = COORDS_PER_VERTEX * 4; // 4 bytes per vertex
this.colors = new float[4*vertexCount];
for (int i = 0; i < colors.length; i+=4) {
colors[i] = 0.63671875f;
colors[i+1] = 0.76953125f;
colors[i+2] = 0.22265625f;
colors[i+3] = 1.0f;
}
// initialize vertex byte buffer for shape coordinates
ByteBuffer bb = ByteBuffer.allocateDirect(
// (number of coordinate values * 4 bytes per float)
triangleCoords.length * 4);
// use the device hardware's native byte order
bb.order(ByteOrder.nativeOrder());
// create a floating point buffer from the ByteBuffer
vertexBuffer = bb.asFloatBuffer();
// add the coordinates to the FloatBuffer
vertexBuffer.put(triangleCoords);
// set the buffer to read the first coordinate
vertexBuffer.position(0);
int vertexShader = MyGLRenderer.loadShader(GLES20.GL_VERTEX_SHADER,
vertexShaderCode);
int fragmentShader = MyGLRenderer.loadShader(GLES20.GL_FRAGMENT_SHADER,
fragmentShaderCode);
// create empty OpenGL ES Program
mProgram = GLES20.glCreateProgram();
// add the vertex shader to program
GLES20.glAttachShader(mProgram, vertexShader);
// add the fragment shader to program
GLES20.glAttachShader(mProgram, fragmentShader);
GLES20.glBindAttribLocation(mProgram, 0, "v_Position");
// GLES20.glBindAttribLocation(mProgram, 1, "vColor");
// creates OpenGL ES program executables
GLES20.glLinkProgram(mProgram);
}
public void draw(float[] mvpMatrix) { // pass in the calculated transformation matrix
// Add program to OpenGL environment
GLES20.glUseProgram(mProgram);
// get handle to vertex shader's vPosition member
mPositionHandle = GLES20.glGetAttribLocation(mProgram, "v_Position");
// if (mPositionHandle == -1) {
// throw new RuntimeException(
// "Could not get attrib location for v_Position");
// }
// Enable a handle to the triangle vertices
GLES20.glEnableVertexAttribArray(mPositionHandle);
// Prepare the triangle coordinate data
GLES20.glVertexAttribPointer(mPositionHandle, COORDS_PER_VERTEX,
GLES20.GL_FLOAT, false,
vertexStride, vertexBuffer);
// get handle to fragment shader's vColor member
mColorHandle = GLES20.glGetUniformLocation(mProgram, "v_Color");
// Set color for drawing the triangle
GLES20.glUniform4fv(mColorHandle, 1, colors, 0);
// get handle to shape's transformation matrix
mMVPMatrixHandle = GLES20.glGetUniformLocation(mProgram, "u_MVPMatrix");
// Apply the projection and view transformation
GLES20.glUniformMatrix4fv(mMVPMatrixHandle, 1, false, mvpMatrix, 0);
// // get handle to shape's transformation matrix
// int mColorHandleU = GLES20.glGetUniformLocation(mProgram, "u_Color");
//
// // Apply the projection and view transformation
// GLES20.glUniform4fv(mColorHandleU, 1, new float[] {}, 0);
// Draw the triangle
GLES20.glDrawArrays(GLES20.GL_TRIANGLES, 0, vertexCount);
// Disable vertex array
GLES20.glDisableVertexAttribArray(mPositionHandle);
}
}
Если я хочу выполнить некоторые необходимые вычисления цвета, мне нужны переменные переменные для передачи информации из вершины в фрагментный шейдер. Однако я не могу этого сделать.
Ошибка, которую я продолжаю получать:
2019-05-14 21:54:25.122 8281-8316/com.example.opengles20 E/emuglGLESv2_enc: device/generic/goldfish-opengl/system/GLESv2_enc/GL2Encoder.cpp:s_glEnableVertexAttribArray:892 GL error 0x501
Info: Invalid vertex attribute index. Wanted index: 4294967295. Max index: 16
2019-05-14 21:54:25.123 8281-8316/com.example.opengles20 E/emuglGLESv2_enc: device/generic/goldfish-opengl/system/GLESv2_enc/GL2Encoder.cpp:s_glVertexAttribPointer:604 GL error 0x501
Info: Invalid vertex attribute index. Wanted index: 4294967295. Max index: 16
2019-05-14 21:54:25.124 8281-8316/com.example.opengles20 E/emuglGLESv2_enc: device/generic/goldfish-opengl/system/GLESv2_enc/GL2Encoder.cpp:s_glDisableVertexAttribArray:901 GL error 0x501
Info: Invalid vertex attribute index. Wanted index: 4294967295. Max index: 16
2019-05-14 21:54:25.237 8281-8316/com.example.opengles20 E/emuglGLESv2_enc: device/generic/goldfish-opengl/system/GLESv2_enc/GL2Encoder.cpp:s_glEnableVertexAttribArray:892 GL error 0x501
Info: Invalid vertex attribute index. Wanted index: 4294967295. Max index: 16
2019-05-14 21:54:25.237 8281-8316/com.example.opengles20 E/emuglGLESv2_enc: device/generic/goldfish-opengl/system/GLESv2_enc/GL2Encoder.cpp:s_glVertexAttribPointer:604 GL error 0x501
Info: Invalid vertex attribute index. Wanted index: 4294967295. Max index: 16
2019-05-14 21:54:25.238 8281-8316/com.example.opengles20 E/emuglGLESv2_enc: device/generic/goldfish-opengl/system/GLESv2_enc/GL2Encoder.cpp:s_glDisableVertexAttribArray:901 GL error 0x501
Info: Invalid vertex attribute index. Wanted index: 4294967295. Max index: 16
Кроме того, при реализации выдается следующее исключение:
mPositionHandle = GLES20.glGetAttribLocation(mProgram, "v_Position");
if (mPositionHandle == -1) {
throw new RuntimeException(
"Could not get attrib location for v_Position");
}
Я знаю, что для атрибутов поток команд выглядит так:
GLES20.glBindAttribLocation(...);
-- Link Shader Program --
attributeHandle = GLES20.glGetAttribLocation(programHandle, "a_AttributenName");
GLES20.glEnableVertexAttribArray(attributeHandle);
GLES20.glVertexAttribPointer(programHandle, ..., buffer);
Последовательность инструкций для униформы выглядит следующим образом:
uniformHandle = GLES20.glGetUniformLocation(mProgram, "u_UniformName");
// do something with it, for example:
GLES20.glUniform4fv(uniformHandle, ...);
Но что делать с переменными переменными?
Заранее спасибо!