OpenGL ES 투시 투영 실현 방법(4)

6681 단어 OpenGLES투시 투영
이전 학습 에서 우 리 는 정점 이 화면 에 나타 나 려 면 x,y,z 의 분량 이 모두[-1,1]사이 에 있어 야 한 다 는 것 을 알 게 되 었 다.우 리 는 렌 더 링 라인 의 그림 조립 단 계 를 돌 이 켜 보 았 다.이 는 실제 적 으로 다음 과 같은 몇 가지 일 을 했다.좌표 커팅,투시 분할,시각 변환 이다.도원 조립의 입력 은 정점 착색 기의 출력 입 니 다.잡 으 세 요.물체 좌표 gl 입 니 다.Position,이후 래 스 터 화 단계.
도원 조립
좌표 편집
정점 착색 기 에 gl 까지 값 을 기록 합 니 다.Position 때 이 점 은 반드시 커팅 공간 에 있어 야 합 니 다.즉,x,y,z 좌 표 는[-w,w]사이 에 있어 야 합 니 다.이 범위 밖의 점 은 보이 지 않 습 니 다.
attribute 형식 에 대한 속성 은 다음 과 같 습 니 다.OpenGL 은 속성 에 지정 되 지 않 은 분량 을 기본 값 으로 바 꿉 니 다.앞의 세 분량 은 0 으로 설정 되 고 마지막 분량 은 w 로 설 정 됩 니 다.
gl 서 있 기position 의 측면 에서 볼 때[-w,w]사이 의 좌표 점 이 야 말로 볼 수 있 고 그렇지 않 으 면 보이 지 않 으 면 잘 릴 것 이다.앞 을 보면 투영 변환 을 할 때 우 리 는 시경 체 내의 물체 가 효과 가 있 고 시경 체 외의 것 은 잘 릴 수 있다 고 말 했다.사실은 대응 하 는 것 이다.가위질 은 도원 조립 단계 에서 발생 하여 모든 좌표 가[-w,w]사이 에 있 는 지 판단 하 는 것 이다.
재단 은 실제 적 으로 모든 최소 삼각형,직선,점 단원 의 좌표 가 규범 적 인지 판단 하 는 것 이다.
투시 제법
위의 커팅 좌표 점 의 x,y,z 좌 표를 w 분량 으로 나 누고 w 의 좌 표를 귀 일화 장치 좌표 라 고 한다.만약 에 w 의 분량 이 크 면 w 를 나 눈 후의 점 은(0,0,0)에 가깝다.3 차원 공간 에서 우리 와 멀리 떨 어 진 좌표 가 만약 에 w 의 분량 이 비교적 크 면 투시 나 누 기 를 한 후에 원점 이 가 까 워 질 수록 원점 은 멀리 있 는 물체 의 사라 진 점 으로서 3 차원 장면 의 효과 가 있다.
시각 변환
앞에서 이미 시각 변환 함수 glViewport 를 사 용 했 습 니 다.시각 은 직사각형 창 영역 입 니 다.OpenGL 렌 더 링 작업 이 최종 적 으로 표 시 된 곳 입 니 다.

public static native void glViewport(
  int x,
  int y,
  int w,
  int h
 );
귀 일화 장치 좌표(x,y,z)에서 창 좌표(X,Y,Z)로 의 전환 공식

위의 공식 중의 f 와 n 은 다음 과 같은 API 설정 입 니 다.

public static native void glDepthRangef(
  float n,
  float f
 );
n,f 가 지정 한 깊이 범위,n,f 의 수 치 는(0.0,1.0)사이 에 국한 되 고 n,f 의 기본 값 은 0.0 과 1.0 이다.
glDepthRangef 함수 와 glViewport 함수 가 지정 한 값 은 정점 위 치 를 귀 일화 장치 좌표 에서 창 좌표 로 변환 하 는 데 사 용 됩 니 다.
w 분량 으로 3 차원 효과 발생
앞의 코드 에서 들 어 오 는 정점 좌 표를 수정 하여 w 분량 을 증가 합 니 다.

float[] vertexArray = new float[] {
   (float) -0.5, (float) -0.5, 0, 1,
   (float) 0.5, (float) -0.5, 0, 1,
   (float) -0.5, (float) 0.5, 0, 3,
   (float) 0.5, (float) 0.5, 0, 3
  };
정점 착색 기 수정:

private String vertexShaderCode = "uniform mat4 uMVPMatrix;"
   + "attribute vec4 aPosition;"
   + "void main(){"
   + "gl_Position = uMVPMatrix * aPosition;"
   + "}";
그리고 uProjectionMatrix 와 정점 데이터 에 대응 하 는 코드 를 가 져 오 면 다음 과 같은 효 과 를 볼 수 있 습 니 다.

투시 투영
그러나 이렇게 해서 물 체 를 3 차원 효 과 를 내 게 하 는 방법 은 너무 딱딱 하 다.만약 에 우리 가 물 체 를 평평 하 게 이동 시 키 고 크기 를 조정 하여 회전 시 키 려 고 한다 면 이렇게 고정된 지정 w 의 값 은 그다지 좋 지 않다.
투시 투영 은 이때 도움 이 되 고 투시 투영 행렬 을 이용 하여 자동 으로 w 의 값 을 생 성 할 수 있다.투영 행렬 은 주로 w 에 정확 한 값 을 만들어 주 는 것 이다.이렇게 렌 더 링 라인 의 후속 작업 에서 투시 나 누 기 를 하면 먼 곳 의 물 체 는 드 나 드 는 물체 보다 작 아 보이 고 꼭대기 위치의 z 분량 을 이용 하여 이 거 리 를 w 분량 에 투사 할 수 있다 는 것 을 쉽게 생각 할 수 있다.z 가 클 수록 w 도 크다.
두 개의 함수 가 투시 투영 행렬 frustumM 과 perspectiveM 을 생 성 할 수 있다.매개 변수 의 구체 적 인 의 미 는 아래 의 그림 을 참고 할 수 있다.

public static void perspectiveM(float[] m, //        
        int offset,
        float fovy, //     
        float aspect, //        
        float zNear, //    
        float zFar) //    
frustumM 함수 원형

public static void frustumM(float[] m, int offset,
 float left, float right, float bottom, float top, //                
 float near, float far //                  
 )

투시 투영 뒤의 수학 원리.
다음 행렬 만 들 기

a 는 시각 초점 거 리 를 나타 내 고 초점 거 리 는 1/tan(시야/2)과 같다.
aspect=1.8,시야 45 도 즉 a=1,f=10,n=5 를 취하 여 얻 은 투시 투영 행렬 은?

아래 의 몇 가지 점 을 계산 하 다

위의 이 세 가지 점 이 점점 멀 어 지고 투시 투영 을 통 해 z 와 w 가 모두 커 졌 다.뒤의 투시 나 누 기 를 할 때 x 와 y 의 분량 이 작 아 지기 때문에 거리 가 멀 어 지고 한 점,즉 3 차원 효과 가 나타 날 것 이 라 고 생각 할 수 있다.
또한 위의 몇 가지 점 을 볼 수 있다.그들의 z 좌 표 는 모두 마이너스 이다.이것 은 측면 에서 표현 한 것 이다.사실은 모든 효과 적 인 점 z 좌 표 는 반드시 마이너스 이다.즉,카메라 의 좌 표를 보면 z 축 마이너스 방향 이다.즉,반드시 시경 체 안에 있어 야 한 다 는 점 은 카메라 행렬 을 통 해 보장 해 야 한다.
앞에서 정교 투영 을 사용 하면 그의 행렬 은 w 분 의 양 을 증가 시 키 지 않 기 때문에 투시 제법 을 통 해 w 의 분량 을 증가 시 키 지 않 기 때문에 정교 투영 은 가 까 운 거리 와 작은 효과 가 나타 나 지 않 고 투시 투영 은 가 까 운 거리 와 작은 효과 가 나타 날 수 있다.
투시 투영 예
위의 사각형 Demo 를 바탕 으로 위의 정사각형 의 정점 데 이 터 를 수정 합 니 다.

float vertices[] = new float[] {
  (float) -0.5, (float) -0.5 + + (float)(-0.1*i), (float) (1*i),
  (float) 0.5, (float) -0.5 + + (float)(-0.1*i), (float) (1*i),
  (float) -0.5, (float) 0.5 + + (float)(-0.1*i), (float) (1*i),
  (float) 0.5, (float) 0.5 + + (float)(-0.1*i), (float) (1*i)
};
그림 을 그 릴 때 하나의 배열 을 정의 하고 서로 다른 i 값 을 전달 합 니 다.예 를 들 어 네 개의 정사각형 을 그립 니 다.이 네 개의 정사각형 의 거 리 는 점점 멀 어 집 니 다.

mRectangles = new Rectangle[5];
   for (int i = 0; i < mRectangles.length; i++) {
    mRectangles[i] = new Rectangle(i); 
   }
onSurface Changed 함수 에 카메라 위치 와 투시 투영 행렬 을 설정 합 니 다.

Matrix.perspectiveM(mProjectionMatrix, 0, 45, (float)width/height, 2, 15);
   Matrix.setLookAtM(mViewMatrix, 0, 0, 0, 12, 0, 0, 0, 0, 1, 0);
그리고 onDrawFram 함수 에 이 5 개의 사각형 을 그립 니 다.

for (Rectangle rectangle : mRectangles) {
  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);
  rectangle.draw(mMVPMatrix);
}
3d 효 과 를 나타 내기 위해 터치 회전 사건 을 증가 시 켜 화면 을 미 끄 러 뜨리 면 3 차원 물체 의 전 모 를 볼 수 있다.

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;
 }
그리고 3 차원 효 과 를 볼 수 있다.

이상 이 바로 본 고의 모든 내용 입 니 다.여러분 의 학습 에 도움 이 되 고 저 희 를 많이 응원 해 주 셨 으 면 좋 겠 습 니 다.

좋은 웹페이지 즐겨찾기