android opengl es 光照效果

这个博客展示了如何在Android中使用OpenGL ES实现3D正方体的光照效果。通过控制光源开关,可以观察到开启和关闭光源时3D正方体的不同显示状态。文章包含Activity和Renderer类的详细代码,涉及顶点、纹理、光照参数的设置以及事件处理。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

通过模拟器左右上下键旋转3d正正方体,中键为光源开关

 

Activity类

 

package sim.feel;

import android.app.Activity;
import android.content.res.Resources;
import android.graphics.Bitmap;
import android.graphics.BitmapFactory;
import android.opengl.GLSurfaceView;
import android.os.Bundle;
import android.view.KeyEvent;

public class My3d extends Activity {
    /** Called when the activity is first created. */

    private MyRenderer renderer = new MyRenderer();
    private GLSurfaceView glSurfaceView;

    @Override
    public void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        BitGL.init(getResources());
        glSurfaceView = new GLSurfaceView(this);
       
        glSurfaceView.setRenderer(renderer);
        setContentView(glSurfaceView);
    }

    // 处理事件
    @Override
    public boolean onKeyDown(int keyCode, KeyEvent event) {
        renderer.onKeyDown(keyCode, event);
        return super.onKeyDown(keyCode, event);
    }

    @Override
    public boolean onKeyUp(int keyCode, KeyEvent event) {
        renderer.onKeyUp(keyCode, event);
        return super.onKeyUp(keyCode, event);
    }

}

class BitGL {
    public static Bitmap bitmap;

    public static void init(Resources resources) {
        bitmap = BitmapFactory.decodeResource(resources, R.drawable.img);
    }
}

 

Renderer类

 

package sim.feel;

import java.nio.ByteBuffer;
import java.nio.ByteOrder;
import java.nio.FloatBuffer;
import java.nio.IntBuffer;

import javax.microedition.khronos.egl.EGLConfig;
import javax.microedition.khronos.opengles.GL10;

import android.opengl.GLSurfaceView.Renderer;
import android.opengl.GLUtils;
import android.view.KeyEvent;

public class MyRenderer implements Renderer {
    float step = 0.4f;
    boolean key;
    boolean light = true;
   
    float xrot, yrot;    //x,y轴旋转
    float xspeed, yspeed;//旋转的速度
    private int one = 0x10000;
    private int[] textures = new int[1];
    /**
     * @param context
     *            顶点及纹理
     */
    // verticesBuffer
    private IntBuffer verticesBuffer;
    // texcoordBuffer
    private IntBuffer texcoordBuffer;
    // 顶点数组vertices
    private int[] vertices;
    // 纹理数组texcoord
    private int[] texcoord;

    /**
     * @param context
     *            光线
     */
    // lightAmbientBuffer
    private FloatBuffer lightAmbientBuffer;
    // 环境光lightAmbient
    private float[] lightAmbient;
    // lightDiffuseBuffer
    private FloatBuffer lightDiffuseBuffer;
    // 漫射光lightDiffuse
    private float[] lightDiffuse;
    // lightPositionBuffer
    private FloatBuffer lightPositionBuffer;
    // 光源的位置
    private float[] lightPosition;


    // 构造方法
    public MyRenderer() {
        // 在构造方法中初始化
        initData();
        initBuffer();
    }

    // 初始化各类值
    public void initData() {
        vertices = new int[] { -one, -one, one, one, -one, one, -one, one, one,
                one, one, one, one, -one, one, one, -one, -one, one, one, one,
                one, one, -one, one, -one, -one, -one, -one, -one, one, one,
                -one, -one, one, -one, -one, -one, -one, -one, -one, one, -one,
                one, -one, -one, one, one, -one, one, -one, one, one, -one,
                -one, one, one, one, one, one, -one, -one, -one, -one, -one,
                one, one, -one, -one, one, -one, one };

        texcoord = new int[] { 0, 0, one, 0, 0, one, one, one };

        lightAmbient = new float[] { 0.5f, 0.5f, 0.5f, 1.0f };

        lightDiffuse = new float[] { 1.0f, 1.0f, 1.0f, 1.0f };

        lightPosition = new float[] { 0.0f, 0.0f, 2.0f, 1.0f };
    }

    public void initBuffer() {
        // verticesbyteBuffer
        ByteBuffer verticesbyteBuffer = ByteBuffer
                .allocateDirect(vertices.length * 4);
        verticesbyteBuffer.order(ByteOrder.nativeOrder());
        verticesBuffer = verticesbyteBuffer.asIntBuffer();
        verticesBuffer.put(vertices);
        verticesBuffer.position(0);

        // texcoordBuffer
        ByteBuffer texcoordbyteBuffer = ByteBuffer
                .allocateDirect(texcoord.length * 4 * 6);
        texcoordbyteBuffer.order(ByteOrder.nativeOrder());
        texcoordBuffer = texcoordbyteBuffer.asIntBuffer();
        for (int i = 0; i < 6; i++) {
            texcoordBuffer.put(texcoord);
        }
        texcoordBuffer.position(0);

        // lightAmbientBuffer
        ByteBuffer lightAmbientbyteBuffer = ByteBuffer
                .allocateDirect(lightAmbient.length * 4 * 6);
        lightAmbientbyteBuffer.order(ByteOrder.nativeOrder());
        lightAmbientBuffer = lightAmbientbyteBuffer.asFloatBuffer();
        lightAmbientBuffer.put(lightAmbient);
        lightAmbientBuffer.position(0);
       
        // lightAmbientBuffer
        ByteBuffer lightPositionbyteBuffer = ByteBuffer
                .allocateDirect(lightPosition.length * 4 * 6);
        lightPositionbyteBuffer.order(ByteOrder.nativeOrder());
        lightPositionBuffer = lightPositionbyteBuffer.asFloatBuffer();
        lightPositionBuffer.put(lightPosition);
        lightPositionBuffer.position(0);
       
        // lightAmbientBuffer
        ByteBuffer lightDiffusebyteBuffer = ByteBuffer
                .allocateDirect(lightDiffuse.length * 4 * 6);
        lightDiffusebyteBuffer.order(ByteOrder.nativeOrder());
        lightDiffuseBuffer = lightDiffusebyteBuffer.asFloatBuffer();
        lightDiffuseBuffer.put(lightDiffuse);
        lightDiffuseBuffer.position(0);
    }

    @Override
    public void onDrawFrame(GL10 gl) {

        // 清除深度缓存和颜色
        gl.glClear(GL10.GL_DEPTH_BUFFER_BIT | GL10.GL_COLOR_BUFFER_BIT);
        // 重置观察模型
        gl.glLoadIdentity();

        //启用光源
        gl.glEnable(GL10.GL_LIGHTING);

        // 启用vertex及texcoord
        gl.glEnableClientState(GL10.GL_VERTEX_ARRAY);
        gl.glEnableClientState(GL10.GL_TEXTURE_COORD_ARRAY);

        // 向左移动1.5f并向里移动6.0f
        gl.glTranslatef(0.0f, 0.0f, -6.0f);
       
        //设置旋转
        gl.glRotatef(xrot, 1.0f, 0.0f, 0.0f);
        gl.glRotatef(yrot, 0.0f, 1.0f, 0.0f);
       
        // 指定顶点映射
        gl.glVertexPointer(3, GL10.GL_FIXED, 0, verticesBuffer);
        // 指定纹理映射(每次都写错,烦)
        gl.glTexCoordPointer(2, GL10.GL_FIXED, 0, texcoordBuffer);

        for (int i = 0; i < 6; i++) {
            gl.glDrawArrays(GL10.GL_TRIANGLE_STRIP, i * 4, 4);
        }

        // 取消顶点及纹理映射
        gl.glDisableClientState(GL10.GL_TEXTURE_COORD_ARRAY);
        gl.glDisableClientState(GL10.GL_VERTEX_ARRAY);

        //旋转角度
        if ( key )
        {
            xrot+=xspeed;
            yrot+=yspeed;
        }
       
        if (!light)                // 判断是否开始光源
        {
            gl.glDisable(GL10.GL_LIGHT1);        // 禁用一号光源
        }
        else                    // 否则
        {
            gl.glEnable(GL10.GL_LIGHT1);        // 启用一号光源
        }

    }

    @Override
    public void onSurfaceChanged(GL10 gl, int width, int height) {
        gl.glViewport(0, 0, width, height);
        float ratio = (float) width / height;
        gl.glMatrixMode(GL10.GL_PROJECTION);
        gl.glLoadIdentity();
        gl.glFrustumf(-ratio, ratio, -1, 1, 1, 10);
        // 设置观察模型
        gl.glMatrixMode(GL10.GL_MODELVIEW);
        gl.glLoadIdentity();
    }

    @Override
    public void onSurfaceCreated(GL10 gl, EGLConfig config) {
        // 告诉系统对透视进行修正
        gl.glHint(GL10.GL_PERSPECTIVE_CORRECTION_HINT, GL10.GL_FASTEST);
        // 设置背景色为黑色
        gl.glClearColor(0, 0, 0, 0);
        // 启用阴影平滑
        gl.glShadeModel(GL10.GL_SMOOTH);

        // 设置深度缓存
        gl.glClearDepthf(one);
        // 启用深度测试
        gl.glEnable(GL10.GL_DEPTH_TEST);
        // 所做深度测试的类型
        gl.glDepthFunc(GL10.GL_LEQUAL);

        // 启用纹理
        gl.glEnable(GL10.GL_TEXTURE_2D); // 不启用没有效果的
        // 创建纹理
        gl.glGenTextures(1, textures, 0);
        // 绑定纹理
        gl.glBindTexture(GL10.GL_TEXTURE_2D, textures[0]);
        // 生成纹理
        GLUtils.texImage2D(GL10.GL_TEXTURE_2D, 0, BitGL.bitmap, 0);

        // 线性滤波
        gl.glTexParameterx(GL10.GL_TEXTURE_2D, GL10.GL_TEXTURE_MIN_FILTER,
                GL10.GL_LINEAR);
        gl.glTexParameterx(GL10.GL_TEXTURE_2D, GL10.GL_TEXTURE_MAG_FILTER,
                GL10.GL_LINEAR);
       
        //设置环境光
        gl.glLightfv(GL10.GL_LIGHT1, GL10.GL_AMBIENT, lightAmbientBuffer);

        //设置漫射光
        gl.glLightfv(GL10.GL_LIGHT1, GL10.GL_DIFFUSE, lightDiffuseBuffer);

        //设置光源的位置
        gl.glLightfv(GL10.GL_LIGHT1, GL10.GL_POSITION, lightPositionBuffer);
       
        //启用一号光源
        gl.glEnable(GL10.GL_LIGHT1);

    }
   
    public boolean onKeyDown(int keyCode, KeyEvent event)
    {
        switch ( keyCode )
        {
            case KeyEvent.KEYCODE_DPAD_UP:
                key = true;
                xspeed=-step;
                break;
            case KeyEvent.KEYCODE_DPAD_DOWN:
                key = true;
                xspeed=step;
                break;
            case KeyEvent.KEYCODE_DPAD_LEFT:
                key = true;
                yspeed=-step;
                break;
            case KeyEvent.KEYCODE_DPAD_RIGHT:
                key = true;
                yspeed=step;
                break;
            case KeyEvent.KEYCODE_DPAD_CENTER:
                light = !light;
                break;
        }
        return false;
    }
   
    public boolean onKeyUp(int keyCode, KeyEvent event)
    {
        key = false;
        return false;
    }


}

 

 

打开光源时效果图:

 

 

 

关闭光源时效果图:

 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值