Android 通过VBO-DynamicScreetBatch将附加数据传递到片段着色器

Android 通过VBO-DynamicScreetBatch将附加数据传递到片段着色器,android,opengl-es,shader,andengine,vbo,Android,Opengl Es,Shader,Andengine,Vbo,我正在使用AndEngine学习opengl着色器,我的目标是使用一些lightshader制作DynamicScreetBatch,其中灯光位置将通过vbo传递到spritebatch中的每个绘制调用,以便我可以在每个sprite上操纵光源 因此,我创建了LightSpriteBatch(使用drawtype.dynamic) 光着色器 public class LightShader extends ShaderProgram { // ===========================

我正在使用AndEngine学习opengl着色器,我的目标是使用一些lightshader制作DynamicScreetBatch,其中灯光位置将通过vbo传递到spritebatch中的每个绘制调用,以便我可以在每个sprite上操纵光源

因此,我创建了LightSpriteBatch(使用drawtype.dynamic)

光着色器

public class LightShader extends ShaderProgram {
// ===========================================================
// Constants
// ===========================================================

private static LightShader INSTANCE;
public static final String ATTRIBUTE_LIGHT_POSITION = "a_lightPosition";
public final static int ATTRIBUTE_LIGHT_POSITION_LOCATION = 4;

public static final String VERTEXSHADER =
        "uniform mat4 " + ShaderProgramConstants.UNIFORM_MODELVIEWPROJECTIONMATRIX + ";\n" +
        "attribute vec4 " + ShaderProgramConstants.ATTRIBUTE_POSITION + ";\n" +
        "attribute vec4 " + ShaderProgramConstants.ATTRIBUTE_COLOR + ";\n" +
        "attribute vec2 " + ShaderProgramConstants.ATTRIBUTE_TEXTURECOORDINATES + ";\n" +
        "attribute vec2 " + LightShader.ATTRIBUTE_LIGHT_POSITION + ";\n" +
        "varying vec4 " + ShaderProgramConstants.VARYING_COLOR + ";\n" +
        "varying vec2 " + ShaderProgramConstants.VARYING_TEXTURECOORDINATES + ";\n" +
        "varying vec2 v_lightPosition;\n" + 
        "void main() {\n" +
        " v_lightPosition = "+ LightShader.ATTRIBUTE_LIGHT_POSITION +" ;\n" +
        "   " + ShaderProgramConstants.VARYING_COLOR + " = " + ShaderProgramConstants.ATTRIBUTE_COLOR + ";\n" +
        "   " + ShaderProgramConstants.VARYING_TEXTURECOORDINATES + " = " + ShaderProgramConstants.ATTRIBUTE_TEXTURECOORDINATES + ";\n" +
        "   gl_Position = " + ShaderProgramConstants.UNIFORM_MODELVIEWPROJECTIONMATRIX + " * " + ShaderProgramConstants.ATTRIBUTE_POSITION + ";\n" +
        "}";




public static final String FRAGMENTSHADER =
        "precision lowp float;\n" +
        "uniform sampler2D " + ShaderProgramConstants.UNIFORM_TEXTURE_0 + ";\n" +
        "varying lowp vec4 " + ShaderProgramConstants.VARYING_COLOR + ";\n" +
        "varying mediump vec2 " + ShaderProgramConstants.VARYING_TEXTURECOORDINATES + ";\n" +
        "varying lowp vec2 v_lightPosition;\n" +
        "void main() {\n" +
        " vec4 tx = texture2D(" + ShaderProgramConstants.UNIFORM_TEXTURE_0 + ", " + ShaderProgramConstants.VARYING_TEXTURECOORDINATES + ") ;"+
        " float u_radius = 100.0;"+
        " vec2 u_lightPosition = vec2(200-50+v_lightPosition.x,200-50+v_lightPosition.y);"+
        " float distance  = length( u_lightPosition - gl_FragCoord.xy );"+
        " float intensity =( 1.5-min( distance, u_radius )/u_radius)*1.5;"+ 
        " gl_FragColor = vec4(tx.r*intensity,tx.g*intensity,tx.b*intensity,tx.w);"+
        "}";

// ===========================================================
// Fields
// ===========================================================

public static int sUniformModelViewPositionMatrixLocation = ShaderProgramConstants.LOCATION_INVALID;
public static int sUniformTexture0Location = ShaderProgramConstants.LOCATION_INVALID;

// ===========================================================
// Constructors
// ===========================================================

private LightShader() {
    super(LightShader.VERTEXSHADER, LightShader.FRAGMENTSHADER);
}

public static LightShader getInstance() {
    if(LightShader.INSTANCE == null) {
        LightShader.INSTANCE = new LightShader();
    }
    return LightShader.INSTANCE;
}

// ===========================================================
// Getter & Setter
// ===========================================================

// ===========================================================
// Methods for/from SuperClass/Interfaces
// ===========================================================

    @Override
protected void link(final GLState pGLState) throws ShaderProgramLinkException {
    GLES20.glBindAttribLocation(this.mProgramID, ShaderProgramConstants.ATTRIBUTE_POSITION_LOCATION, ShaderProgramConstants.ATTRIBUTE_POSITION);
    GLES20.glBindAttribLocation(this.mProgramID, ShaderProgramConstants.ATTRIBUTE_COLOR_LOCATION, ShaderProgramConstants.ATTRIBUTE_COLOR);
    GLES20.glBindAttribLocation(this.mProgramID, ShaderProgramConstants.ATTRIBUTE_TEXTURECOORDINATES_LOCATION, ShaderProgramConstants.ATTRIBUTE_TEXTURECOORDINATES);
    GLES20.glBindAttribLocation(this.mProgramID, ShaderProgramConstants.ATTRIBUTE_POSITION_0_LOCATION, ShaderProgramConstants.ATTRIBUTE_POSITION_0);
    super.link(pGLState);

    LightShader.sUniformModelViewPositionMatrixLocation = this.getUniformLocation(ShaderProgramConstants.UNIFORM_MODELVIEWPROJECTIONMATRIX);
    LightShader.sUniformTexture0Location = this.getUniformLocation(ShaderProgramConstants.UNIFORM_TEXTURE_0);
}

@Override
public void bind(final GLState pGLState, final VertexBufferObjectAttributes pVertexBufferObjectAttributes) {
    GLES20.glEnableVertexAttribArray(ShaderProgramConstants.ATTRIBUTE_POSITION_0_LOCATION);
    super.bind(pGLState, pVertexBufferObjectAttributes);
    GLES20.glUniformMatrix4fv(LightShader.sUniformModelViewPositionMatrixLocation, 1, false, pGLState.getModelViewProjectionGLMatrix(), 0);
    GLES20.glUniform1i(LightShader.sUniformTexture0Location, 0);
}


    @Override
public void unbind(GLState pGLState) throws ShaderProgramException {
    GLES20.glDisableVertexAttribArray(ShaderProgramConstants.ATTRIBUTE_POSITION_0_LOCATION);
    super.unbind(pGLState);
}

// ===========================================================
// Methods
// ===========================================================

// ===========================================================
// Inner and Anonymous Classes
// ===========================================================
}

我还创建了自定义的HighPerformanceLightSpriteBatchVBO,在这里我将灯光位置传递到缓冲区

@Override
public void addWithPackedColor(final ITextureRegion pTextureRegion, final float pX1, final float pY1, final float pX2, final float pY2, final float pColorABGRPackedInt,final float pLightXX,final float pLightYY) {
    final float[] bufferData = this.getBufferData();
    final int bufferDataOffset = this.mBufferDataOffset;

    final float x1 = pX1;
    final float y1 = pY1;
    final float x2 = pX2;
    final float y2 = pY2;
    final float u = pTextureRegion.getU();
    final float v = pTextureRegion.getV();
    final float u2 = pTextureRegion.getU2();
    final float v2 = pTextureRegion.getV2();
    final float pLightX = pLightXX;
    final float pLightY = pLightYY;

    if(pTextureRegion.isRotated()) {
        bufferData[bufferDataOffset + 0 * LightSpriteBatch.VERTEX_SIZE + LightSpriteBatch.VERTEX_INDEX_X] = x1;
        bufferData[bufferDataOffset + 0 * LightSpriteBatch.VERTEX_SIZE + LightSpriteBatch.VERTEX_INDEX_Y] = y1;
        bufferData[bufferDataOffset + 0 * LightSpriteBatch.VERTEX_SIZE + LightSpriteBatch.COLOR_INDEX] = pColorABGRPackedInt;
        bufferData[bufferDataOffset + 0 * LightSpriteBatch.VERTEX_SIZE + LightSpriteBatch.TEXTURECOORDINATES_INDEX_U] = u;
        bufferData[bufferDataOffset + 0 * LightSpriteBatch.VERTEX_SIZE + LightSpriteBatch.TEXTURECOORDINATES_INDEX_V] = v;
        bufferData[bufferDataOffset + 0 * LightSpriteBatch.VERTEX_SIZE + LightSpriteBatch.LIGHT_POSITION_INDEX_X] = pLightX;
        bufferData[bufferDataOffset + 0 * LightSpriteBatch.VERTEX_SIZE + LightSpriteBatch.LIGHT_POSITION_INDEX_Y] = pLightY;
所有这些都可以工作,但我在片段着色器中读取此光照位置时遇到问题。如果渲染纹理,我需要做什么计算来正确计算灯光位置和位置之间的距离

DynamicLightSpriteBatch sb = new DynamicLightSpriteBatch(mTextureSprite,10,getVertexBufferObjectManager()) {
        @Override
        protected boolean onUpdateSpriteBatch() {
             draw(mTextureSpriteRegion, 0f, 0f, 400f, 400f, 0f, 1.0f, 1.0f, 1.0f, 1.0f,100f,100f); // ( 100,100 = lightX & Y ) 
            return true;
        }
    };

灯光始终位于中心(200半径/2200半径/2),应将其移动100100作为最后一个参数

如果我理解正确,您希望的是在片段着色器中具有相对灯光位置,每个像素的相对位置不同。为此,您需要访问顶点着色器中的modelview和投影矩阵,并计算要传递给片段着色器的精灵的
up
right
向量。然后在“片段着色器”(fragment shader)中,将其(乘以texcoord)添加到精灵中心位置,以获得每个着色片段(精灵的每个像素)的世界空间位置。从灯光位置减去它,瞧


请注意,在着色器代码中,对于顶点/片段着色器中的
变量,似乎有不同的精度说明符。这可能会导致问题(变量可能不链接,因此顶点着色器中输出的值被丢弃,而片段着色器中的输入值未定义)。这是OpenGL的一个暗角,某种程度上是因为需要能够任意混合和匹配不同的顶点和片段着色器。

您也可以发布着色器代码吗?有(顶部的第二个片段)LightShader
DynamicLightSpriteBatch sb = new DynamicLightSpriteBatch(mTextureSprite,10,getVertexBufferObjectManager()) {
        @Override
        protected boolean onUpdateSpriteBatch() {
             draw(mTextureSpriteRegion, 0f, 0f, 400f, 400f, 0f, 1.0f, 1.0f, 1.0f, 1.0f,100f,100f); // ( 100,100 = lightX & Y ) 
            return true;
        }
    };