2013-01-23 41 views
8

Tôi đang học bóng mờ với AndEngine, mục tiêu của tôi là tạo DynamicSpriteBatch với một số lighthader nơi vị trí ánh sáng sẽ được truyền qua vbo tới mỗi cuộc gọi vẽ trong spritebatch để tôi có thể điều khiển ánh sáng nguồn trên mọi sprite.Vượt qua dữ liệu bổ sung cho trình đổ bóng phân đoạn qua VBO - DynamicSpriteBatch

Vì vậy, tôi đã tạo ra LightSpriteBatch (với drawtype.dynamic)

public class LightSpriteBatch extends Shape { 
// =========================================================== 
// Constants 
// =========================================================== 

private static final float[] VERTICES_TMP = new float[8]; 

private static final Transformation TRANSFORATION_TMP = new Transformation(); 

public static final int VERTEX_INDEX_X = 0; 
public static final int VERTEX_INDEX_Y = 1; 

public static final int COLOR_INDEX = 2; 

public static final int TEXTURECOORDINATES_INDEX_U = 3; 
public static final int TEXTURECOORDINATES_INDEX_V = 4; 

public static final int LIGHT_POSITION_INDEX_X = 5; 
public static final int LIGHT_POSITION_INDEX_Y = 6 
     ; 

public static final int VERTEX_SIZE = 2 + 1 + 2 + 2 ; 
public static final int VERTICES_PER_SPRITE = 6; 
public static final int SPRITE_SIZE = VERTEX_SIZE * VERTICES_PER_SPRITE; 


public static final VertexBufferObjectAttributes VERTEXBUFFEROBJECTATTRIBUTES_DEFAULT = new VertexBufferObjectAttributesBuilder(4) 
.add(ShaderProgramConstants.ATTRIBUTE_POSITION_LOCATION, ShaderProgramConstants.ATTRIBUTE_POSITION, 2, GLES20.GL_FLOAT, false) 
.add(ShaderProgramConstants.ATTRIBUTE_COLOR_LOCATION, ShaderProgramConstants.ATTRIBUTE_COLOR, 4, GLES20.GL_UNSIGNED_BYTE, true) 
.add(ShaderProgramConstants.ATTRIBUTE_TEXTURECOORDINATES_LOCATION, ShaderProgramConstants.ATTRIBUTE_TEXTURECOORDINATES, 2, GLES20.GL_FLOAT, false) 
.add(LightShader.ATTRIBUTE_LIGHT_POSITION_LOCATION, LightShader.ATTRIBUTE_LIGHT_POSITION, 2, GLES20.GL_FLOAT, false) 
.build(); 
LightShader

tùy chỉnh

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 
// =========================================================== 

}

Tôi cũng tạo HighPerformanceLightSpriteBatchVBO nơi tôi đang đi qua vị trí ánh sáng vào đệm

@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; 

với tất cả những điều này nó hoạt động nhưng tôi có vấn đề đọc ánh sáng này trong shader mảnh. Những tính toán tôi cần phải làm gì để tính toán khoảng cách đúng cách giữa vị trí ánh sáng và vị trí nếu kết cấu được hiển thị?

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; 
     } 
    }; 

ánh sáng luôn luôn là trung tâm (200-radius/2.200-radius/2) và nó sẽ được chuyển bởi 100.100 như các thông số cuối cùng

+1

Bạn cũng có thể đăng mã shader không? – Kimi

+0

Có (đoạn thứ hai từ trên xuống) LightShader –

Trả lời

0

Nếu tôi hiểu nó một cách chính xác những gì bạn muốn là có liên quan vị trí ánh sáng trong trình đổ bóng phân đoạn, khác với mỗi pixel. Để thực hiện điều đó, bạn cần truy cập vào các ma trận modelview và ma trận chiếu trong vertex shader và tính toán các vectơ upright cho sprite của bạn được chuyển tới shader fragment. Sau đó, trong shader fragment thêm này (nhân với texcoord) vào vị trí trung tâm của sprite để có được vị trí không gian thế giới của từng mảnh mờ (mỗi pixel của sprite). Trừ nó từ vị trí ánh sáng và thì đấy!

Lưu ý rằng trong mã trình đổ bóng của bạn, bạn dường như có một số thông số chính xác khác nhau cho các biến số varying trong các trình đổ bóng đỉnh/đoạn. Điều đó có thể dẫn đến các vấn đề (các thay đổi có thể không liên kết, sao cho giá trị được xuất ra trong đổ bóng đỉnh được bỏ đi và giá trị đầu vào trong đổ bóng phân đoạn không được xác định). Đây là một trong những góc tối của OpenGL, phần nào gây ra bởi các yêu cầu để có thể tự ý trộn và kết hợp các vertex khác nhau và các shader fragment.

Các vấn đề liên quan