Hallo,
ich arbeite an einem 3D-Spiel mit OpenGl 2.0. Soweit läuft alles, jedoch sehr ruckelig. Meine einzelnen Models, welche sich in einer ArrayList befinden, werden in onDrawFrame einzeln mithilfe der Methode renderModel (siehe unten) an die Shader übermittelt. Ich habe herausgefunden, dass die einzelnen Models zwischen "0" - 2 Millisekunden benötigen, um ihre Daten an OpenGL zu übermitteln. Zusammengerechnet kommen da Werte von bis zu 100 ms pro Frame heraus, was ja nicht normal sein kann... (oder liege ich da falsch?)
Die einzelnen zu übergebenen Daten werden in java.nio.Buffer-Instanzen (bzw. FloatBuffer, ...) gespeichert und dann direkt an GL übergeben. Hier mein Code:
@Override
public void renderModel(AGScene scene, Object modelTransform, AGModel model) {
Model b = (Model) model;
int count = b.getCount();
de.ab.agf.lib.math.AGArrays.copy((float[]) modelTransform, 0, modelMatrix, 0, 16);
Matrix.setIdentityM(MVPMatrix, 0);
Matrix.multiplyMM(MVPMatrix, 0, viewMatrix, 0, modelMatrix, 0);
Matrix.multiplyMM(MVPMatrix, 0, projectionMatrix, 0, MVPMatrix, 0);
//pass data
//uniforms
GLES20.glUniformMatrix4fv(uMMatrix, 1, false, modelMatrix, 0);
GLES20.glUniformMatrix4fv(uMVPMatrix, 1, false, MVPMatrix, 0);
GLES20.glUniform1i(uTex, 0);
GLES20.glUniform1i(uTexEnabled, b.getTexEnabled() ? 1 : 0);
GLES20.glUniform1i(uLOShadeless, b.getLShadeless() ? 1 : 0);
GLES20.glUniform3fv(uLOAmbient, 1, b.getLAmbient());
GLES20.glUniform3fv(uLODiffuse, 1, b.getLDiffuse());
GLES20.glUniform3fv(uLOSpecular, 1, b.getLSpecular());
//attrs
addAttrFArray(aPosition, 3, b.getCoordinates());
addAttrFArray(aColor, 4, b.getColors());
addAttrFArray(aTexPosition, 2, b.getTexCoordinates());
addAttrFArray(aNormal, 3, b.getNormals());
if (b.getTexEnabled()) {
GLES20.glActiveTexture(GLES20.GL_TEXTURE0);
GLES20.glBindTexture(GLES20.GL_TEXTURE_2D, ((TextureStore) scene.getTextureStore()).getDataForKey(b.getTexture()));
}
GLES20.glDrawElements(GLES20.GL_TRIANGLES, count, GLES20.GL_UNSIGNED_SHORT, b.getDrawOrder());
//disable passed attr arrays
GLES20.glDisableVertexAttribArray(aPosition);
GLES20.glDisableVertexAttribArray(aColor);
GLES20.glDisableVertexAttribArray(aTexPosition);
GLES20.glDisableVertexAttribArray(aNormal);
}
private void addAttrFArray(int handle, int partCount, FloatBuffer data) {
if (data != null) {
GLES20.glVertexAttribPointer(handle, partCount, GLES20.GL_FLOAT, false, partCount * 4, data);
GLES20.glEnableVertexAttribArray(handle);
}
}
Alles anzeigen
Das Model (Z. 3) ist eine Klasse, die die einzelnen Buffer und weiteren Eigenschaften bereit stellt.
In den Zeilen 7 - 10 werden die einzelnen Matrizen zusammengerechnet.
Anschließend werden die entsprechenden Parameter an OpenGL übergeben und gezeichnet.
Danach werden die VertexAttribArrays deaktiviert, um das nächste Model zeichnen zu können.
Shader:
Fragment-Shader:
precision mediump float;
uniform sampler2D u_Tex;
uniform int u_TexEnabled;
varying vec4 v_Color;
varying vec2 v_TexPosition;
void main() {
if (u_TexEnabled == 1)
gl_FragColor = v_Color * texture2D(u_Tex, v_TexPosition);
else
gl_FragColor = v_Color;
}
Alles anzeigen
In meinem Fragment-Shader wird nur die Farbe übergeben.
In meinem Vertex-Shader wird diffuses und ambientes Licht berechnet (spekulares Licht habe ich momentan nicht eingebaut, da ich es nicht unbedingt benötige) und an den Fragment-Shader übergeben.
Zudem werden Texturen-Koordinaten (TexPosition) an den Fragment-Shader übergeben.
Zuletzt werden die Vertex-Koordinaten an GL übergeben.
Vertex-Shader:
#define MAX_LAMPS (8)
#define TYPE_SUN (0.0)
#define TYPE_POINT (1.0)
#define TYPE_SPOTLIGHT (2.0)
#define ATTR_POINT_STRENGTH (0)
#define ATTR_SPOTLIGHT_ANGLE (1)
#define ATTR_SPOTLIGHT_HARDNESS (2)
uniform mat4 u_MMatrix;
uniform mat4 u_MVPMatrix;
uniform int u_LLCount;
uniform float u_LLType[MAX_LAMPS];
uniform mat4 u_LLMatrix[MAX_LAMPS];
uniform vec3 u_LLColor[MAX_LAMPS];
uniform vec3 u_LLDirection[MAX_LAMPS];
uniform vec3 u_LLAttributes[MAX_LAMPS];
uniform int u_LOShadeless;
uniform vec3 u_LOAmbient;
uniform vec3 u_LODiffuse;
uniform vec3 u_LOSpecular;
attribute vec4 a_Position;
attribute vec4 a_Color;
attribute vec2 a_TexPosition;
attribute vec3 a_Normal;
varying vec4 v_Color;
varying vec2 v_TexPosition;
float getDiffuse(int lamp) {
if (u_LLType[lamp] == TYPE_SUN) {
vec4 vNormal = u_MMatrix * vec4(a_Normal, 0.0);
vec4 vLamp = u_LLMatrix[lamp] * vec4(u_LLDirection[lamp], 0.0);
float dot = dot(normalize(vNormal), normalize(vLamp));
return max(-dot, 0.0);
}
if (u_LLType[lamp] == TYPE_POINT) {
vec4 vNormal = u_MMatrix * vec4(a_Normal, 0.0);
vec4 vLamp = (u_LLMatrix[lamp] * vec4(0.0, 0.0, 0.0, 1.0)) - (u_MMatrix * a_Position);
float dot = dot(normalize(vNormal), normalize(vLamp));
float cut = max(dot, 0.0);
float distance = length(vLamp);
float att = cut * (1.0 / (1.0 + ((1.0 - min(u_LLAttributes[lamp][ATTR_POINT_STRENGTH], 1.0)) * distance * distance)));
return max(min(att, 1.0), 0.0);
}
if (u_LLType[lamp] == TYPE_SPOTLIGHT) {
//spotlight calculations
}
return 0.0;
}
void main() {
if (u_LOShadeless == 1)
v_Color = a_Color;
else {
vec3 diffuse;
for(int i = 0; i < u_LLCount && i < MAX_LAMPS; i ++)
diffuse += u_LLColor[i] * getDiffuse(i);
v_Color = a_Color * (vec4(u_LODiffuse * diffuse, 1.0) + vec4(u_LOAmbient, 1.0));
}
v_TexPosition = a_TexPosition;
gl_Position = u_MVPMatrix * a_Position;
}
Alles anzeigen
Hat jemand eine Idee, woran das liegen kann?
Liebe Grüße, Aaron