【问题标题】:Why isn't this Android specular lighting example working as intended?为什么这个 Android 镜面光照示例没有按预期工作?
【发布时间】:2010-12-13 18:30:03
【问题描述】:

为什么以下代码生成的二进制文件中没有出现镜面高光?

package com.example.helloandroid;

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

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

import android.opengl.GLSurfaceView.Renderer;

public class TestRenderer implements Renderer {
    private FloatBuffer vb;
    private FloatBuffer mab, mdb, msb;

    private FloatBuffer lPos;
    private FloatBuffer lab, ldb, lsb;

    public TestRenderer() {
        vb = ByteBuffer.allocateDirect(24 * 4).order(ByteOrder.nativeOrder()).asFloatBuffer();
        vb.put(new float[]{
            110.0f, 240.0f,
            110.0f, 190.0f,
            160.0f, 240.0f,
            160.0f, 190.0f,
            210.0f, 240.0f,
            210.0f, 190.0f,
            110.0f, 290.0f,
            110.0f, 240.0f,
            160.0f, 290.0f,
            160.0f, 240.0f,
            210.0f, 290.0f,
            210.0f, 240.0f});
        vb.position(0);
        mab = ByteBuffer.allocateDirect(4 * 4).order(ByteOrder.nativeOrder()).asFloatBuffer();
        mab.put(new float[]{1.0f, 0.0f, 0.0f, 1.0f});
        mab.position(0);
        mdb = ByteBuffer.allocateDirect(4 * 4).order(ByteOrder.nativeOrder()).asFloatBuffer();
        mdb.put(new float[]{0.0f, 1.0f, 0.0f, 1.0f});
        mdb.position(0);
        msb = ByteBuffer.allocateDirect(4 * 4).order(ByteOrder.nativeOrder()).asFloatBuffer();
        msb.put(new float[]{0.0f, 0.0f, 1.0f, 1.0f});
        msb.position(0);

        lPos = ByteBuffer.allocateDirect(4 * 4).order(ByteOrder.nativeOrder()).asFloatBuffer();
        lPos.put(new float[]{160.0f, 240.0f, 10.0f, 1.0f});
        lPos.position(0);
        lab = ByteBuffer.allocateDirect(4 * 4).order(ByteOrder.nativeOrder()).asFloatBuffer();
        // THIS WORKS..
        lab.put(new float[]{0.0f, 0.0f, 0.0f, 1.0f});
        lab.position(0);
        ldb = ByteBuffer.allocateDirect(4 * 4).order(ByteOrder.nativeOrder()).asFloatBuffer();
        // SO DOES THIS..
        ldb.put(new float[]{0.0f, 0.0f, 0.0f, 1.0f});
        ldb.position(0);
        // BUT NOT THIS
        lsb = ByteBuffer.allocateDirect(4 * 4).order(ByteOrder.nativeOrder()).asFloatBuffer();
        lsb.put(new float[]{1.0f, 1.0f, 1.0f, 1.0f});
        lsb.position(0);
    }

    @Override
    public void onSurfaceCreated(GL10 gl, EGLConfig config) {
        gl.glClearColor(0.0f, 0.0f, 0.0f, 1.0f);

        gl.glEnable(GL10.GL_LIGHTING);
        gl.glEnableClientState(GL10.GL_VERTEX_ARRAY);

        gl.glMaterialfv(GL10.GL_FRONT, GL10.GL_AMBIENT, mab);
        gl.glMaterialfv(GL10.GL_FRONT, GL10.GL_DIFFUSE, mdb);
        gl.glMaterialfv(GL10.GL_FRONT, GL10.GL_SPECULAR, msb);

        gl.glLightfv(GL10.GL_LIGHT0, GL10.GL_POSITION, lPos);
        gl.glLightfv(GL10.GL_LIGHT0, GL10.GL_AMBIENT, lab);
        gl.glLightfv(GL10.GL_LIGHT0, GL10.GL_DIFFUSE, ldb);
        gl.glLightfv(GL10.GL_LIGHT0, GL10.GL_SPECULAR, lsb);
        gl.glEnable(GL10.GL_LIGHT0);
    }

    @Override
    public void onSurfaceChanged(GL10 gl, int width, int height) {
        gl.glViewport(0, 0, width, height);

        gl.glMatrixMode(GL10.GL_PROJECTION);
        gl.glLoadIdentity();
        gl.glOrthof(0.0f, width, 0.0f, height, -1.0f, 1.0f);

        gl.glMatrixMode(GL10.GL_MODELVIEW);
        gl.glLoadIdentity();
        gl.glTranslatef(0.0f, 0.0f, -1.0f);
    }

    @Override
    public void onDrawFrame(GL10 gl) {
        gl.glClear(GL10.GL_COLOR_BUFFER_BIT);

        gl.glVertexPointer(2, GL10.GL_FLOAT, 0, vb);
        gl.glNormal3f(0.0f, 0.0f, 1.0f);
        gl.glDrawArrays(GL10.GL_TRIANGLE_STRIP, 0, 6);
        gl.glDrawArrays(GL10.GL_LINE_STRIP, 6, 6);
    }
}

这是我从代码中看到的内容(只有一个镜面光照组件):http://i.imgur.com/4kvIx.png

仅使用环境照明组件:http://i.imgur.com/80Tjx.png

只有一个漫反射照明组件:http://i.imgur.com/r5PkO.png

可能有趣的是,我调用 glOrtho 中的 zNear/zFar 参数似乎没有剪裁任何东西。我是否正确设置了场景以查看镜面高光(我确实尝试将灯光定位在顶点附近)?

【问题讨论】:

    标签: android opengl-es lighting normals


    【解决方案1】:

    OpenGL ES 只接受 GL_FRONT_AND_BACK。在此处查看 glMaterial

    http://www.khronos.org/opengles/sdk/1.1/docs/man/glMaterial.xml

    【讨论】:

      【解决方案2】:

      嗯,在我的头撞到墙上几个小时后,我决定在设备上实际运行代码而不仅仅是模拟器上的新想法。难道你不知道,经过一些调整,它似乎工作正常!

      这是一个新示例,其中包含我所做的更改和一个更好的场景来说明感知到的问题:

      package com.example.helloandroid;
      
      import java.nio.ByteBuffer;
      import java.nio.ByteOrder;
      import java.nio.FloatBuffer;
      
      import javax.microedition.khronos.egl.EGLConfig;
      import javax.microedition.khronos.opengles.GL10;
      
      import android.opengl.GLSurfaceView.Renderer;
      import android.opengl.GLU;
      
      public class TestRenderer implements Renderer {
          private int rows;
          private int cols;
      
          private FloatBuffer vb;
          private FloatBuffer mab, mdb, msb;
      
          private FloatBuffer lPos;
          private FloatBuffer lab, ldb, lsb;
      
          public TestRenderer(int rows, int cols) {
              this.rows = rows;
              this.cols = cols;
      
              vb = ByteBuffer.allocateDirect(4 * (rows - 1) * cols * 4).order(ByteOrder.nativeOrder()).asFloatBuffer();
              for(int row = 0; row < (rows - 1); ++row)
                  for(int col = 0; col < cols; ++col) {
                      vb.put(col * 320.0f / (cols - 1)); vb.put((row + 1) * 480.0f / (rows - 1));
                      vb.put(col * 320.0f / (cols - 1)); vb.put(row * 480.0f / (rows - 1));
                  }
              vb.position(0);
      //      vb = ByteBuffer.allocateDirect(24 * 4).order(ByteOrder.nativeOrder()).asFloatBuffer();
      //      vb.put(new float[]{
      //          0.0f, 50.0f,
      //          0.0f, 0.0f,
      //          50.0f, 50.0f,
      //          50.0f, 0.0f,
      //          100.0f, 50.0f,
      //          100.0f, 0.0f,
      //          0.0f, 100.0f,
      //          0.0f, 50.0f,
      //          50.0f, 100.0f,
      //          50.0f, 50.0f,
      //          100.0f, 100.0f,
      //          100.0f, 50.0f});
      //      vb.position(0);
              mab = ByteBuffer.allocateDirect(4 * 4).order(ByteOrder.nativeOrder()).asFloatBuffer();
              mab.put(new float[]{1.0f, 0.0f, 0.0f, 1.0f});
              mab.position(0);
              mdb = ByteBuffer.allocateDirect(4 * 4).order(ByteOrder.nativeOrder()).asFloatBuffer();
              mdb.put(new float[]{0.0f, 1.0f, 0.0f, 1.0f});
              mdb.position(0);
              msb = ByteBuffer.allocateDirect(4 * 4).order(ByteOrder.nativeOrder()).asFloatBuffer();
              msb.put(new float[]{0.0f, 0.0f, 1.0f, 1.0f});
              msb.position(0);
      
              lPos = ByteBuffer.allocateDirect(4 * 4).order(ByteOrder.nativeOrder()).asFloatBuffer();
              lPos.put(new float[]{-180.0f, 0.0f, 300.0f, 1.0f});
              lPos.position(0);
              lab = ByteBuffer.allocateDirect(4 * 4).order(ByteOrder.nativeOrder()).asFloatBuffer();
              // THIS WORKS..
              lab.put(new float[]{0.1f, 0.0f, 0.0f, 1.0f});
              lab.position(0);
              ldb = ByteBuffer.allocateDirect(4 * 4).order(ByteOrder.nativeOrder()).asFloatBuffer();
              // SO DOES THIS..
              ldb.put(new float[]{0.0f, 0.1f, 0.0f, 1.0f});
              ldb.position(0);
              // BUT NOT THIS
              lsb = ByteBuffer.allocateDirect(4 * 4).order(ByteOrder.nativeOrder()).asFloatBuffer();
              lsb.put(new float[]{0.0f, 0.0f, 1.0f, 1.0f});
              lsb.position(0);
          }
      
          @Override
          public void onSurfaceCreated(GL10 gl, EGLConfig config) {
              gl.glClearColor(0.0f, 0.0f, 0.0f, 1.0f);
      
              gl.glEnable(GL10.GL_LIGHTING);
              gl.glEnableClientState(GL10.GL_VERTEX_ARRAY);
      
              gl.glMaterialfv(GL10.GL_FRONT_AND_BACK, GL10.GL_AMBIENT, mab);
              gl.glMaterialfv(GL10.GL_FRONT_AND_BACK, GL10.GL_DIFFUSE, mdb);
              gl.glMaterialfv(GL10.GL_FRONT_AND_BACK, GL10.GL_SPECULAR, msb);
              gl.glMaterialf(GL10.GL_FRONT_AND_BACK, GL10.GL_SHININESS, 128.0f);
      
              gl.glLightfv(GL10.GL_LIGHT0, GL10.GL_POSITION, lPos);
              gl.glLightfv(GL10.GL_LIGHT0, GL10.GL_AMBIENT, lab);
              gl.glLightfv(GL10.GL_LIGHT0, GL10.GL_DIFFUSE, ldb);
              gl.glLightfv(GL10.GL_LIGHT0, GL10.GL_SPECULAR, lsb);
              gl.glEnable(GL10.GL_LIGHT0);
      
              gl.glDisable(GL10.GL_TEXTURE);
              gl.glFrontFace(GL10.GL_CCW);
          }
      
          @Override
          public void onSurfaceChanged(GL10 gl, int width, int height) {
              gl.glViewport(0, 0, width, height);
      
              gl.glMatrixMode(GL10.GL_PROJECTION);
              gl.glLoadIdentity();
      //      gl.glOrthof(0.0f, width, 0.0f, height, -1.0f, 1.0f);
              GLU.gluPerspective(gl, 45.0f, (float)width / (float)height, 999.0f, 1001.0f);
      
              gl.glMatrixMode(GL10.GL_MODELVIEW);
          }
      
          @Override
          public void onDrawFrame(GL10 gl) {
              gl.glClear(GL10.GL_COLOR_BUFFER_BIT);
      
              gl.glLoadIdentity();
              gl.glTranslatef(-160.0f, -240.0f, -1000.0f);
      
              gl.glVertexPointer(2, GL10.GL_FLOAT, 0, vb);
              gl.glNormal3f(0.0f, 0.0f, 1.0f);
              for(int row = 0; row < rows - 1; ++row) {
                  gl.glDrawArrays(GL10.GL_TRIANGLE_STRIP, 2 * row * cols, 2 * cols);
      //          gl.glDrawArrays(GL10.GL_LINE_STRIP, 2 * row * cols, 2 * cols);
              }
      //      gl.glDrawArrays(GL10.GL_TRIANGLE_STRIP, 0, 6);
      //      gl.glDrawArrays(GL10.GL_LINE_STRIP, 6, 6);
          }
      
      }
      

      我遇到的最大的奇怪是必须从 GL_FRONT 切换到 GL_FRONT_AND_BACK,我不知道为什么它不能只使用 GL_FRONT(或者只是 GL_BACK,我也尝试过,以防我的绕组向后或什么的)。

      这是模拟器上的新示例:i.imgur.com/ldAND.png

      在实际设备上:i.imgur.com/Ukqqm.png

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 1970-01-01
        • 2022-10-14
        • 2020-07-24
        • 2011-11-20
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        相关资源
        最近更新 更多