OpenGL ES 빛 효과 구현(6)

13138 단어 OpenGLES빛 효과
빛 의 효 과 를 보 여주 기 위해 앞에서 배 운 내용 을 바탕 으로 우 리 는 먼저 큐 브 를 만 들 었 다.또한 직관 적 으로 보이 기 위해 이 큐 브 는 각 면 에 중심 이 흰색 이 고 주변 빨간색 의 그 라 데 이 션 방안 을 사용 했다.그렇지 않 으 면 똑 같은 색 이 섞 여 있어 큐 브 인지 아 닌 지 알 수 없다.그리고 회전 회전 기능 을 추가 하면 회전 하면 입체 감 이 더욱 강하 다.
입방체
입방체 류 Rectangle.java

public class Rectangle {
  private FloatBuffer mVertexBuffer;
  private int mProgram;
  private int mPositionHandle;
  private int muMVPMatrixHandle;
  private int mColorHandle;

  public Rectangle(float r) {
    initVetexData(r);
  }
  public void initVetexData(float i) {
    float vertices[] = new float[] {
        //        
        //  
         0, 0, 1, 1,1,1,0,
         1, 1, 1, 1,0,0,0,
        -1, 1, 1, 1,0,0,0,
         0, 0, 1, 1,1,1,0,
        -1, 1, 1, 1,0,0,0,
        -1,-1, 1, 1,0,0,0,
         0, 0, 1, 1,1,1,0,
        -1,-1, 1, 1,0,0,0,
         1,-1, 1, 1,0,0,0,
         0, 0, 1, 1,1,1,0,
         1,-1, 1, 1,0,0,0,
         1, 1, 1, 1,0,0,0,
         //  
         0, 0,-1, 1,1,1,0,
         1, 1,-1, 1,0,0,0,
         1,-1,-1, 1,0,0,0,
         0, 0,-1, 1,1,1,0,
         1,-1,-1, 1,0,0,0,
        -1,-1,-1, 1,0,0,0,
         0, 0,-1, 1,1,1,0,
        -1,-1,-1, 1,0,0,0,
        -1, 1,-1, 1,0,0,0,
         0, 0,-1, 1,1,1,0,
        -1, 1,-1, 1,0,0,0,
         1, 1,-1, 1,0,0,0,
        //  
        -1, 0, 0, 1,1,1,0,
        -1, 1, 1, 1,0,0,0,
        -1, 1,-1, 1,0,0,0,
        -1, 0, 0, 1,1,1,0,
        -1, 1,-1, 1,0,0,0,
        -1,-1,-1, 1,0,0,0,
        -1, 0, 0, 1,1,1,0,
        -1,-1,-1, 1,0,0,0,
        -1,-1, 1, 1,0,0,0,
        -1, 0, 0, 1,1,1,0,
        -1,-1, 1, 1,0,0,0,
        -1, 1, 1, 1,0,0,0,
        //  
         1, 0, 0, 1,1,1,0,
         1, 1, 1, 1,0,0,0,
         1,-1, 1, 1,0,0,0,
         1, 0, 0, 1,1,1,0,
         1,-1, 1, 1,0,0,0,
         1,-1,-1, 1,0,0,0,
         1, 0, 0, 1,1,1,0,
         1,-1,-1, 1,0,0,0,
         1, 1,-1, 1,0,0,0,
         1, 0, 0, 1,1,1,0,
         1, 1,-1, 1,0,0,0,
         1, 1, 1, 1,0,0,0,
         //  
         0, 1, 0, 1,1,1,0,
         1, 1, 1, 1,0,0,0,
         1, 1,-1, 1,0,0,0,
         0, 1, 0, 1,1,1,0,   
         1, 1,-1, 1,0,0,0,
        -1, 1,-1, 1,0,0,0,
         0, 1, 0, 1,1,1,0,
        -1, 1,-1, 1,0,0,0,
        -1, 1, 1, 1,0,0,0,
         0, 1, 0, 1,1,1,0,
        -1, 1, 1, 1,0,0,0,
         1, 1, 1, 1,0,0,0,
        //  
         0,-1, 0, 1,1,1,0,
         1,-1, 1, 1,0,0,0,
        -1,-1, 1, 1,0,0,0,
         0,-1, 0, 1,1,1,0,
        -1,-1, 1, 1,0,0,0,
        -1,-1,-1, 1,0,0,0,
         0,-1, 0, 1,1,1,0,
        -1,-1,-1, 1,0,0,0,
         1,-1,-1, 1,0,0,0,
         0,-1, 0, 1,1,1,0,
         1,-1,-1, 1,0,0,0,
         1,-1, 1, 1,0,0,0,
      };

    ByteBuffer vbb = ByteBuffer.allocateDirect(vertices.length * 4);
    vbb.order(ByteOrder.nativeOrder());
    mVertexBuffer = vbb.asFloatBuffer();
    mVertexBuffer.put(vertices);
    mVertexBuffer.position(0);

    int vertexShader = loaderShader(GLES20.GL_VERTEX_SHADER,
        vertexShaderCode);
    int fragmentShader = loaderShader(GLES20.GL_FRAGMENT_SHADER,
        fragmentShaderCode);

    mProgram = GLES20.glCreateProgram();
    GLES20.glAttachShader(mProgram, vertexShader);
    GLES20.glAttachShader(mProgram, fragmentShader);
    GLES20.glLinkProgram(mProgram);

    mPositionHandle = GLES20.glGetAttribLocation(mProgram, "aPosition");
    mColorHandle = GLES20.glGetAttribLocation(mProgram, "aColor");
    muMVPMatrixHandle = GLES20.glGetUniformLocation(mProgram, "uMVPMatrix");
  }

  public void draw(float[] mvpMatrix) {
    GLES20.glUseProgram(mProgram);
    //           ,     
    //      0,    
    mVertexBuffer.position(0);
    // stride   ,            
    GLES20.glVertexAttribPointer(mPositionHandle, 3, GLES20.GL_FLOAT, false, (4+3) * 4, mVertexBuffer);
    //           ,     
    //      3,    
    mVertexBuffer.position(3);
    GLES20.glVertexAttribPointer(mColorHandle, 4, GLES20.GL_FLOAT, false, (4+3) * 4, mVertexBuffer);
    GLES20.glEnableVertexAttribArray(mPositionHandle);
    GLES20.glEnableVertexAttribArray(mColorHandle);
    GLES20.glUniformMatrix4fv(muMVPMatrixHandle, 1, false, mvpMatrix, 0);
    GLES20.glDrawArrays(GLES20.GL_TRIANGLES, 0, 12*6);
  }

  private int loaderShader(int type, String shaderCode) {
    int shader = GLES20.glCreateShader(type);
    GLES20.glShaderSource(shader, shaderCode);
    GLES20.glCompileShader(shader);
    return shader;
  }

  private String vertexShaderCode = "uniform mat4 uMVPMatrix;"
      + "attribute vec4 aColor;"
      + "varying vec4 aaColor;"
      + "attribute vec3 aPosition;"
      + "void main(){"
      + "gl_Position = uMVPMatrix * vec4(aPosition,1);"
      + "aaColor = aColor;"
      + "}";

  private String fragmentShaderCode = "precision mediump float;"
      + "varying vec4 aaColor;"
      + "void main(){"
      + "gl_FragColor = aaColor;"
      + "}";
}
initVetexData 류 는 앞의 예 와 대체적으로 같 지만 앞 과 다른 부분 이 있 습 니 다.정점 을 정의 할 때 안에 정점 의 좌 표를 정의 할 뿐만 아니 라 정점 의 색 도 정 의 했 습 니 다.즉,좌표 와 정점 이 데이터 버퍼 에 놓 여 있 기 때문에 읽 을 때glVertex AttribpPointer 함 수 를 호출 하려 면 stride 매개 변수 가 정확 한 값 으로 들 어 오 는 것 을 주의 하고 정점 좌표 값 을 가지 고 놀 러 간 후에 ByteBuffer 의 position 를 첫 번 째 색상 값 이 시작 되 는 곳 으로 다시 설정 해 야 합 니 다.
RectangleView.java

public class RectangleView extends GLSurfaceView{

  private float mPreviousY;
  private float mPreviousX;
  MyRender mMyRender;
  public RectangleView(Context context) {
    super(context);
    setEGLContextClientVersion(2);
    mMyRender = new MyRender();
    setRenderer(mMyRender);
  }

  public boolean onTouchEvent(MotionEvent e) {
    float y = e.getY();
    float x = e.getX();
    switch (e.getAction()) {
    case MotionEvent.ACTION_MOVE:
      float dy = y - mPreviousY;
      float dx = x - mPreviousX;
      mMyRender.yAngle += dx;
      mMyRender.xAngle+= dy;
      requestRender();
    }
    mPreviousY = y;
    mPreviousX = x;
    return true;
  }

  class MyRender implements GLSurfaceView.Renderer {
    private Rectangle mRectangle;
    float yAngle;
    float xAngle;
    @Override
    public void onSurfaceCreated(GL10 gl, EGLConfig config) {
      GLES20.glClearColor(1, 1, 1, 1);
      mRectangle = new Rectangle();
      GLES20.glEnable(GLES20.GL_DEPTH_TEST);
    }

    @Override
    public void onSurfaceChanged(GL10 gl, int width, int height) {
      GLES20.glViewport(0, 0, width, height);
      Matrix.perspectiveM(mProjectionMatrix, 0, 45, (float)width/height, 5, 15);
      Matrix.setLookAtM(mViewMatrix, 0, 0, 0, 10, 0, 0, 0, 0, 1, 0);
    }

    private final float[] mProjectionMatrix = new float[16];
    private final float[] mViewMatrix = new float[16];
    private final float[] mModuleMatrix = new float[16];
    private final float[] mViewProjectionMatrix = new float[16];
    private final float[] mMVPMatrix = new float[16];
    @Override
    public void onDrawFrame(GL10 gl) {
      GLES20.glClear( GLES20.GL_DEPTH_BUFFER_BIT | GLES20.GL_COLOR_BUFFER_BIT);
      Matrix.setIdentityM(mModuleMatrix, 0);
      Matrix.rotateM(mModuleMatrix, 0, xAngle, 1, 0, 0);
      Matrix.rotateM(mModuleMatrix, 0, yAngle, 0, 1, 0);
      Matrix.multiplyMM(mViewProjectionMatrix, 0, mProjectionMatrix, 0, mViewMatrix, 0);
      Matrix.multiplyMM(mMVPMatrix, 0, mViewProjectionMatrix, 0, mModuleMatrix, 0);
      mRectangle.draw(mMVPMatrix, mModuleMatrix);
    }
  }
}
생 긴 효과

아직 은 실 감 이 나 지 않 는 것 처럼 보인다.자연계 에 빛 의 영향 이 있 기 때문이다.이 글 은 위의 입방체 에 대해 빛 을 넣 었 다.
라이트 모델
빛 모형 은 환경 광,산란 광,거울 면 광 을 포함 한 세 가지 가 있다.
환경 광
환경 광:사방팔방 에서 물체 에 비 치 는 전방위 적 으로 균일 한 빛 은 현실 세계 에서 광원 에서 여러 번 반 사 된 후에 각 방향 이 대체적으로 균일 한 빛 을 발사 하 는 것 을 대표 한다.환경 광 은 광원 위치 에 의존 하지 않 고 방향 성 이 없다.환경 빛 의 입사 가 고 르 고 반사 도 고르다.
환경 광 최종 강도
필름 착색 기 를 수정 하면 다음 과 같이 환경 빛 의 효 과 를 실현 할 수 있다.

gl_FragColor = aaColor*vec4(0.5,0.5,0.5,1);
환경 광 을 넣 은 후의 효 과 는 다음 과 같 습 니 다.효과 가 매우 좋 지 않 은 것 을 볼 수 있 습 니 다.왜냐하면 각 지역 의 빛 은 똑 같 고 차이 가 없 기 때 문 입 니 다.

산란 광
산사 광:물체 표면 에서 전방위 360 도로 고 르 게 반사 되 는 빛 은 현실 세계 에서 거 친 물체 표면 이 빛 에 비 칠 때 각 방향 으로 반사 되 는 것 이 기본적으로 고 르 며 만반 사로 도 불 린 다.산사 광의 강도 와 입사각 의 관계 가 매우 커서 입사 각도 가 작 을 수록 밝다.
산란 광 최종 강도=산란 광 강 도 는 8727°max{0,(cos)θ)}
그 속θ입사각
산란 광의 설명도

다음은 주로 정점 착색 기의 코드 를 수정 하면 된다.

private String vertexShaderCode = "uniform mat4 uMVPMatrix;"
      + "uniform mat4 uMMatrix;" //        
      + "uniform vec3 uLightLocation;" //     
      + "attribute vec4 aColor;"
      + "varying vec4 vColor;" 
      + "varying vec4 vDiffuse;" //               ,      
      + "attribute vec3 aPosition;" //     
      + "void main(){" 
      + "vec3 normalVectorOrigin = aPosition;" //         
      + "vec3 normalVector = normalize((uMMatrix*vec4(normalVectorOrigin,1)).xyz);" //            
      + "vec3 vectorLight = normalize(uLightLocation - (uMMatrix * vec4(aPosition,1)).xyz);" //            
      + "float factor = max(0.0, dot(normalVector, vectorLight));"
      + "vDiffuse = factor*vec4(1,1,1,1.0);" //      ,      
      + "gl_Position = uMVPMatrix * vec4(aPosition,1);"
      + "vColor = aColor;"
      + "}";
필름 착색 기

private String fragmentShaderCode = "precision mediump float;"
      + "varying vec4 vColor;"
      + "varying vec4 vDiffuse;" //                  ,         。
      + "void main(){"
      + "gl_FragColor = vColor*vDiffuse;" //             
      + "}";
위의 주요 코드 의 미 는 이미 주석 에 추가 되 었 다.그리고 다음 과 같은 몇 가지 주의 가 필요 합 니 다.
4.567917.정점 착색 기 에서 MVP 행렬 을 제외 하고 M 행렬 도 들 어 왔 다.그 이 유 는 분명 하 다.빛 이 물체 에 비 추 면 계산 법 선과 이 정점 과 광원 의 위 치 는 반드시 기본 적 인 변환(확대 와 회전)작업 을 한 후의 위 치 를 사용 해 야 한다.그 위 에 M 행렬 이 들 어 오 는 목적 은 바로 여기에 있다4.567917.유량 에 대한 점 적:ab=|a|b|cosa.따라서 협각 의 코사인 을 계산 하려 면 벡터 를 계산 점 에 획일 화하 면 됩 니 다4.567917.특정한 점 의 법 적 벡터,점 의 법 적 벡터 는 이 점 의 절단면 이 수직 으로 밖으로 향 하 는 벡터 로 정의 된다.불규칙 한 모양 에 대해 법 선 을 찾 는 방법 은 임계 점 으로 구 성 된 평면 적 인 법 적 벡터 를 찾 는 것 이 고 인접 한 향 량 의 평균 법 적 벡터 를 구 할 수 있다.
이 어 정점 과 메타 착색 기 를 수정 한 후 코드 에 uMMatrix,uLightLocation 의 참조 및 착색 기 에 데 이 터 를 전달 하 는 코드 를 추가 합 니 다.

muMMatrixHandle = GLES20.glGetUniformLocation(mProgram, "uMMatrix");
muLightLocationHandle = GLES20.glGetUniformLocation(mProgram, "uLightLocation");
...
GLES20.glUniformMatrix4fv(muMMatrixHandle, 1, false, mMatrix, 0);
GLES20.glUniform3f(muLightLocationHandle, 0, 0, 20); 

 //            ,                  
산란 광선 의 효 과 를 증가 시 켜 서 효과 가 현저히 좋아 진 것 을 볼 수 있 습 니 다.어떤 곳 은 비교적 어 둡 고 어떤 곳 은 검 습 니 다.빛 이 비치 지 않 았 기 때 문 입 니 다.산란 광 은 광원 의 각도 와 관련 이 있 기 때문에 각도 가 작 을 수록 밝 아 지 는 것 이 자연계의 진실 한 현상 이기 때문이다.

코드 다운로드
거울빛
거울 빛:현실 세계 에서 매 끄 러 운 표면 이 비 친 후에 방향 이 매우 집 중 된 반사광 이 있다.이런 반사광 은 바로 거울 빛 이다.거울 빛 은 입사 각 에 의존 하 는 것 외 에 관찰자(카메라)의 위치 에 도 의존한다.만약 에 카메라 가 비 친 점 의 벡터 가 반사광 이 집 중 된 범위 안에 있 지 않 으 면 거울 빛 을 볼 수 없다.
거울 빛 의 최종 강도=거울 빛 의 강 도 는 8727°max{0,(cos)θ)α}
그 속θθ반 벡터 와 법 벡터 의 협각 을 말한다.αα거칠다
거울 면 광 설명도

거울 빛 을 사용 할 때 는 카메라 행렬 을 정점 착색 기 에 전달 하고 계산 방법 은 정의 에 따라 만 하면 된다.
환경 광,산란 광,거울 빛 을 종합 한 모형

gl_FragColor = vColor*vec4(0.5,0.5,0.5,1) + vColor*vDiffuse + vColor*vSpecular
이상 이 바로 본 고의 모든 내용 입 니 다.여러분 의 학습 에 도움 이 되 고 저 희 를 많이 응원 해 주 셨 으 면 좋 겠 습 니 다.

좋은 웹페이지 즐겨찾기