gpt4 book ai didi

Android OPEN GL ES 2 fragment 着色器

转载 作者:行者123 更新时间:2023-11-29 14:09:13 24 4
gpt4 key购买 nike

我在使用 Open GL ES 2 fragment 着色器时遇到问题,想知道是否有人可以帮助我。

我正在使用着色器在屏幕上绘制变形球。比较简单,代码如下:

private static final String mFragmentShader = "precision mediump float;\n"
+ "uniform vec2 balls["
+ NUMBER_OF_BALLS
+ "];\n"
+ "float sqr(highp float x) { return x*x; }\n"
+ "void main() {\n"
+ " vec4 pixelColor = vec4(0.0, 0.0, 0.0, 0.0);\n"
+ " vec4 color = vec4(0.0, 0.5, 1.0, 1.0);\n"
+ " for (int i=0; i<"
+ NUMBER_OF_BALLS
+ "; ++i) {\n"
+ " vec2 dist = balls[i] - gl_FragCoord.xy;\n"
+ " float val = 100.0 / (sqr(dist.x) + sqr(dist.y));\n"
+ " pixelColor += color * val;\n"
+ " }\n"
+ " highp float a = smoothstep(0.9, 1.0, pixelColor.a);\n"
+ " gl_FragColor = vec4(pixelColor.rgb * a, 1.0);\n"
+ "}\n";

当 NUMBER_OF_BALLS 小于 15 时,着色器编译良好并且运行良好。不幸的是,当球的数量大于 15 时,它呈现为好像所有球的位置都在位置 (0,0)(参见 here ).我已经检查了着色器的输入,肯定是正确的,所以一定是着色器本身有问题。此外,如果我将精度从 mediump 更改为 high,那么我可以在渲染成为问题之前将球的数量增加到 20。

谁能告诉我我做错了什么?

编辑:这是完整的代码,以防 fragment 着色器本身没有问题。

       private static final String mFragmentShader = "precision mediump float;\n"
+ "uniform vec2 balls["
+ NUMBER_OF_BALLS
+ "];\n"
+ "float sqr(highp float x) { return x*x; }\n"
+ "void main() {\n"
+ " vec4 pixelColor = vec4(0.0, 0.0, 0.0, 0.0);\n"
+ " vec4 color = vec4(0.0, 0.5, 1.0, 1.0);\n"
+ " for (int i=0; i<"
+ NUMBER_OF_BALLS
+ "; ++i) {\n"
+ " vec2 dist = balls[i] - gl_FragCoord.xy;\n"
+ " float val = 100.0 / (sqr(dist.x) + sqr(dist.y));\n"
+ " pixelColor += color * val;\n"
+ " }\n"
+ " highp float a = smoothstep(0.9, 1.0, pixelColor.a);\n"
+ " gl_FragColor = vec4(pixelColor.rgb * a, 1.0);\n"
+ "}\n";



private static final String mVertexShader = "attribute vec4 vPosition;\n" + "void main() {\n"
+ " gl_Position = vPosition;\n"
+ "}\n";

int gProgram;
int gvPositionHandle;

private float[][] balls = new float[NUMBER_OF_BALLS][2];

int[] lBalls = new int[NUMBER_OF_BALLS];

private static final int FLOAT_SIZE_BYTES = 4;

private final float[] mQuadVerticesData = { 1.0f, 1.0f, -1.0f, 1.0f, -1.0f, -1.0f, 1.0f, -1.0f, };

private FloatBuffer mQuadVertices;

public MetaballRenderer() {
mQuadVertices = ByteBuffer.allocateDirect(mQuadVerticesData.length * FLOAT_SIZE_BYTES)
.order(ByteOrder.nativeOrder())
.asFloatBuffer();
mQuadVertices.put(mQuadVerticesData).position(0);
}

private int loadShader(int shaderType, String source) {
int shader = GLES20.glCreateShader(shaderType);
if (shader != 0) {
GLES20.glShaderSource(shader, source);
GLES20.glCompileShader(shader);
int[] compiled = new int[1];
GLES20.glGetShaderiv(shader, GLES20.GL_COMPILE_STATUS, compiled, 0);
if (compiled[0] == 0) {
Log.e(TAG, "Could not compile shader " + shaderType + ":");
Log.e(TAG, GLES20.glGetShaderInfoLog(shader));
GLES20.glDeleteShader(shader);
shader = 0;
}
}
return shader;
}

private int createProgram(String vertexSource, String fragmentSource) {
int vertexShader = loadShader(GLES20.GL_VERTEX_SHADER, vertexSource);
if (vertexShader == 0) {
return 0;
}

int pixelShader = loadShader(GLES20.GL_FRAGMENT_SHADER, fragmentSource);
if (pixelShader == 0) {
return 0;
}

int program = GLES20.glCreateProgram();
if (program != 0) {
GLES20.glAttachShader(program, vertexShader);
checkGlError("glAttachShader");
GLES20.glAttachShader(program, pixelShader);
checkGlError("glAttachShader");
GLES20.glLinkProgram(program);
int[] linkStatus = new int[1];
GLES20.glGetProgramiv(program, GLES20.GL_LINK_STATUS, linkStatus, 0);
if (linkStatus[0] != GLES20.GL_TRUE) {
Log.e(TAG, "Could not link program: ");
Log.e(TAG, GLES20.glGetProgramInfoLog(program));
GLES20.glDeleteProgram(program);
program = 0;
}
}
return program;
}


private void init_balls() {
for (int i = 0; i < NUMBER_OF_BALLS; ++i) {
balls[i][0] = 200 + rand.nextInt(50);
balls[i][1] = 200 + rand.nextInt(50);
}
}

private void checkGlError(String op) {
int error;
while ((error = GLES20.glGetError()) != GLES20.GL_NO_ERROR) {
Log.e(TAG, op + ": glError " + error);
throw new RuntimeException(op + ": glError " + error);
}
}

@Override
public void onDrawFrame(GL10 arg0) {

GLES20.glUseProgram(gProgram);
checkGlError("glUseProgram");

for (int i = 0; i < NUMBER_OF_BALLS; ++i) {
GLES20.glUniform2fv(i, 1, balls[i], 0);
checkGlError("glUniform2fv");
}

GLES20.glVertexAttribPointer(gvPositionHandle, 2, GLES20.GL_FLOAT, false, 0, mQuadVertices);
checkGlError("glVertexAttribPointer");
GLES20.glEnableVertexAttribArray(gvPositionHandle);
checkGlError("glEnableVertexAttribArray");

GLES20.glDrawArrays(GLES20.GL_TRIANGLE_FAN, 0, 4);
checkGlError("glDrawArrays");

GLES20.glUseProgram(0);
checkGlError("glUseProgram");

}

@Override
public void onSurfaceChanged(GL10 glUnused, int width, int height) {

// Ignore the passed-in GL10 interface, and use the GLES20
// class's static methods instead.
gProgram = createProgram(mVertexShader, mFragmentShader);
if (gProgram == 0) {
return;
}

gvPositionHandle = GLES20.glGetAttribLocation(gProgram, "vPosition");
checkGlError("glGetAttribLocation");
init_balls();
for (int i = 0; i < NUMBER_OF_BALLS; ++i) {
lBalls[i] = GLES20.glGetUniformLocation(gProgram, "balls[" + i + "]");
checkGlError("glGetUniformLocation");
}

GLES20.glViewport(0, 0, width, height);
checkGlError("glViewport");

}

@Override
public void onSurfaceCreated(GL10 arg0, EGLConfig arg1) {

}

最佳答案

这段代码:

for (int i = 0; i < NUMBER_OF_BALLS; ++i) {
GLES20.glUniform2fv(i, 1, balls[i], 0);
checkGlError("glUniform2fv");
}

是不对的。您将 [0, NUMBER_OF_BALLS-1] 中的 i 作为统一位置传递,但必须使用 glGetUniformLocation 从 OpenGL 获取统一位置。

关于Android OPEN GL ES 2 fragment 着色器,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/4633896/

24 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com