본문 바로가기

카테고리 없음

안드로이드 OpenGL ES 2 예제, Pixel Shader Lighting

Per-Vertex Lighting과 Per-Pixel Lighting의 비교

원문출처: http://www.learnopengles.com/android-lesson-three-moving-to-per-fragment-lighting/

아래의 예제를 모바일 기기에서 실행하면 다음과 같은 결과를 확인할  수 있다.

Activity class

package gl.test1;


import android.app.Activity;

import android.app.ActivityManager;

import android.content.Context;

import android.content.pm.ConfigurationInfo;

import android.opengl.GLSurfaceView;

import android.os.Bundle;


public class PerFragmentActivity extends Activity 

{

private GLSurfaceView mGLSurfaceView;


@Override

public void onCreate(Bundle savedInstanceState) 

{

super.onCreate(savedInstanceState);

mGLSurfaceView = new GLSurfaceView(this);


// Check if the system supports OpenGL ES 2.0.

final ActivityManager activityManager = (ActivityManager) getSystemService(Context.ACTIVITY_SERVICE);

final ConfigurationInfo configurationInfo = activityManager.getDeviceConfigurationInfo();

final boolean supportsEs2 = configurationInfo.reqGlEsVersion >= 0x20000;


if (supportsEs2) 

{

// Request an OpenGL ES 2.0 compatible context.

mGLSurfaceView.setEGLContextClientVersion(2);


// Set the renderer to our demo renderer, defined below.

mGLSurfaceView.setRenderer(new LessonThreeRenderer());

else 

{

// This is where you could create an OpenGL ES 1.x compatible

// renderer if you wanted to support both ES 1 and ES 2.

return;

}

setContentView(mGLSurfaceView);

}


@Override

protected void onResume() 

{

// The activity must call the GL surface view's onResume() on activity onResume().

super.onResume();

mGLSurfaceView.onResume();

}


@Override

protected void onPause() 

{

// The activity must call the GL surface view's onPause() on activity onPause().

super.onPause();

mGLSurfaceView.onPause();

}

}


Renderer class

package gl.test1;



/**

 * This class implements our custom renderer. Note that the GL10 parameter passed in is unused for OpenGL ES 2.0

 * renderers -- the static class GLES20 is used instead.

 */

public class LessonThreeRenderer extends LessonTwoRenderer

{

protected String getVertexShader()

{

// Define our per-pixel lighting shader.

        final String perPixelVertexShader =

"uniform mat4 u_MVPMatrix;      \n" // A constant representing the combined model/view/projection matrix.

 + "uniform mat4 u_MVMatrix;       \n" // A constant representing the combined model/view matrix.

 

 + "attribute vec4 a_Position;     \n" // Per-vertex position information we will pass in.

 + "attribute vec4 a_Color;        \n" // Per-vertex color information we will pass in.

 + "attribute vec3 a_Normal;       \n" // Per-vertex normal information we will pass in.

 

 + "varying vec3 v_Position;       \n" // This will be passed into the fragment shader.

 + "varying vec4 v_Color;          \n" // This will be passed into the fragment shader.

 + "varying vec3 v_Normal;         \n" // This will be passed into the fragment shader.

 

// The entry point for our vertex shader.  

 + "void main()                                                \n"

 + "{                                                          \n"

// Transform the vertex into eye space.

 + "   v_Position = vec3(u_MVMatrix * a_Position);             \n"

// Pass through the color.

 + "   v_Color = a_Color;                                      \n"

// Transform the normal's orientation into eye space.

 + "   v_Normal = vec3(u_MVMatrix * vec4(a_Normal, 0.0));      \n"

// gl_Position is a special variable used to store the final position.

// Multiply the vertex by the matrix to get the final point in normalized screen coordinates.

 + "   gl_Position = u_MVPMatrix * a_Position;                 \n"        

 + "}                                                          \n";      

return perPixelVertexShader;

}

protected String getFragmentShader()

{

final String perPixelFragmentShader =

"precision mediump float;       \n" // Set the default precision to medium. We don't need as high of a 

// precision in the fragment shader.

 + "uniform vec3 u_LightPos;       \n"    // The position of the light in eye space.

 

 + "varying vec3 v_Position; \n" // Interpolated position for this fragment.

 + "varying vec4 v_Color;          \n" // This is the color from the vertex shader interpolated across the 

  // triangle per fragment.

 + "varying vec3 v_Normal;         \n" // Interpolated normal for this fragment.

 

// The entry point for our fragment shader.

 + "void main()                    \n"

 + "{                              \n"

// Will be used for attenuation.

 + "   float distance = length(u_LightPos - v_Position);                  \n"

// Get a lighting direction vector from the light to the vertex.

 + "   vec3 lightVector = normalize(u_LightPos - v_Position);             \n"

// Calculate the dot product of the light vector and vertex normal. If the normal and light vector are

// pointing in the same direction then it will get max illumination.

 + "   float diffuse = max(dot(v_Normal, lightVector), 0.1);              \n"      

// Add attenuation. 

 + "   diffuse = diffuse * (1.0 / (1.0 + (0.25 * distance * distance)));  \n"

// Multiply the color by the diffuse illumination level to get final output color.

 + "   gl_FragColor = v_Color * diffuse;                                  \n"

 + "}                                                                     \n";

return perPixelFragmentShader;

}

}