如何在某些操作后更改现有对象的颜色

时间:2017-06-11 06:54:24

标签: android opengl-es

我正在绘制一个简单的3D形状。从.obj文件中读取形状,整个形状有一种颜色。 我想创造一种改变颜色的可能性。例如,如果我点击按钮,我想让结构变红。

我已经阅读了很多教程,但我无法弄清楚如何在运行时更改颜色(重绘元素?)。我在onDrawFrame

中尝试过类似的东西
gl.glEnableClientState(GL10.GL_COLOR_ARRAY);
            gl.glMaterialfv(GL10.GL_FRONT_AND_BACK, GL10.GL_AMBIENT, colorBuffer);
            gl.glDisableClientState(GL10.GL_COLOR_ARRAY);

但没有任何改变。

我应该在何处以及如何实施此类行动?

//更新

绘制方法

if(!initialized) {
            init(gl);
            initialized = true;
        }
        if(glCameraMatrixBuffer != null) {
            glMatrixBuffer.put(glMatrix);
            glMatrixBuffer.position(0);

            //argDrawMode3D
            gl.glMatrixMode(GL10.GL_MODELVIEW);
            gl.glLoadIdentity();
            //argDraw3dCamera
            gl.glMatrixMode(GL10.GL_PROJECTION);
            gl.glLoadMatrixf( glCameraMatrixBuffer );

            gl.glMatrixMode(GL10.GL_MODELVIEW);
            gl.glLoadMatrixf(glMatrixBuffer);
        }

gl.glEnableClientState(GL10.GL_NORMAL_ARRAY);
        gl.glEnableClientState(GL10.GL_VERTEX_ARRAY);
        gl.glEnableClientState(GL10.GL_COLOR_ARRAY);
        gl.glVertexPointer(3, GL10.GL_FLOAT, 0, vertexBuffer);
        gl.glMaterialfv(GL10.GL_FRONT_AND_BACK, GL10.GL_AMBIENT, colorBuffer);

        for(int i=0; i<parts.size(); i++){
            TDModelPart t=parts.get(i);
            Material m=t.getMaterial();

            if(m!=null){
                FloatBuffer a=m.getAmbientColorBuffer();
                FloatBuffer d=m.getDiffuseColorBuffer();
                FloatBuffer s=m.getSpecularColorBuffer();
                gl.glMaterialfv(GL10.GL_FRONT_AND_BACK,GL10.GL_AMBIENT,a);
                gl.glMaterialfv(GL10.GL_FRONT_AND_BACK,GL10.GL_SPECULAR,s);
                gl.glMaterialfv(GL10.GL_FRONT_AND_BACK,GL10.GL_DIFFUSE,d);
            }

            gl.glNormalPointer(GL10.GL_FLOAT, 0, t.getNormalBuffer());

            gl.glDrawElements(GL10.GL_TRIANGLES,t.getFacesCount(),GL10.GL_UNSIGNED_SHORT,t.getFaceBuffer());
        }


        gl.glDisableClientState(GL10.GL_COLOR_ARRAY);
        gl.glDisableClientState(GL10.GL_VERTEX_ARRAY);
        gl.glDisableClientState(GL10.GL_NORMAL_ARRAY);

public final void onDrawFrame(GL10 gl) {
        gl.glClear(GL10.GL_COLOR_BUFFER_BIT | GL10.GL_DEPTH_BUFFER_BIT);

        if (DEBUG) {
            gl = (GL10) GLDebugHelper.wrap(gl, GLDebugHelper.CONFIG_CHECK_GL_ERROR, log);
        }
        setupDraw2D(gl);
        gl.glDisable(GL10.GL_DEPTH_TEST);
        gl.glEnable(GL10.GL_TEXTURE_2D);
        gl.glDisable(GL10.GL_LIGHTING);
        gl.glBindTexture(GL10.GL_TEXTURE_2D, textureName);
        //load new preview frame as a texture, if needed
        if (frameEnqueued) {
            frameLock.lock();
            if (!isTextureInitialized) {
                initializeTexture(gl);
            } else {
                //just update the image
                //can we just update a portion(non power of two)?...seems to work
                gl.glTexSubImage2D(GL10.GL_TEXTURE_2D, 0, 0, 0, previewFrameWidth, previewFrameHeight,
                        mode, GL10.GL_UNSIGNED_BYTE, frameData);
            }
            frameLock.unlock();
            gl.glTexParameterf(GL10.GL_TEXTURE_2D, GL10.GL_TEXTURE_MIN_FILTER, GL10.GL_LINEAR);
            gl.glTexParameterf(GL10.GL_TEXTURE_2D, GL10.GL_TEXTURE_MAG_FILTER, GL10.GL_LINEAR);
            frameEnqueued = false;
        }

        gl.glColor4f(1, 1, 1, 1f);
        //draw camera preview frame:
        gl.glEnableClientState(GL10.GL_TEXTURE_COORD_ARRAY);
        gl.glEnableClientState(GL10.GL_VERTEX_ARRAY);

        gl.glTexCoordPointer(2, GL10.GL_FLOAT, 0, textureBuffer);
        gl.glVertexPointer(3, GL10.GL_FLOAT, 0, squareBuffer);

        //draw camera square
        gl.glDrawArrays(GL10.GL_TRIANGLE_STRIP, 0, 4);

        gl.glDisableClientState(GL10.GL_TEXTURE_COORD_ARRAY);
        gl.glDisableClientState(GL10.GL_VERTEX_ARRAY);

        if (customRenderer != null) {
            customRenderer.setupEnv(gl);
        } else {
//          gl.glEnable(GL10.GL_LIGHTING);
//          gl.glLightfv(GL10.GL_LIGHT0, GL10.GL_AMBIENT, ambientLightBuffer);
//          gl.glLightfv(GL10.GL_LIGHT0, GL10.GL_DIFFUSE, diffuseLightBuffer);
//          gl.glLightfv(GL10.GL_LIGHT0, GL10.GL_SPECULAR, specularLightBuffer);
//          gl.glLightfv(GL10.GL_LIGHT0, GL10.GL_POSITION, lightPositionBuffer);
//          gl.glEnable(GL10.GL_LIGHT0);
        }

        matrixGrabber.getCurrentState(gl);

        if (performAction) {
            Log.d("ZMIANA_KOLORY", "akcja się wola");
            int[] c = new int[]{255, 0, 0};
            Vector<Float> v = markerInfo.getObjects().get(0).vectors;
            ByteBuffer vBuf = ByteBuffer.allocateDirect(v.size() * 4);
            vBuf.order(ByteOrder.nativeOrder());
            float[] newColor = new float[c.length + 1];
            for (int i = 0; i < c.length; i++) {
                newColor[i] = (1.0f / 255) * c[i];
                newColor[3] = 1.0f;
            }

            Log.d("ZMIANA_KOLORY", newColor[0] + " " + newColor[1] + " " + newColor[2] + " " + newColor[3] + " ");

            FloatBuffer colorBuffer = vBuf.asFloatBuffer();
            colorBuffer.put(newColor);
            colorBuffer.position(0);
            gl.glEnableClientState(GL10.GL_COLOR_ARRAY);
            gl.glMaterialfv(GL10.GL_FRONT_AND_BACK, GL10.GL_AMBIENT, colorBuffer);
            gl.glDisableClientState(GL10.GL_COLOR_ARRAY);

            performAction = false;
//          Log.d("PERFORM_ACTION", "wykonuję akcję: " + actionName);
//          switch (actionName) {
//              case "Highlight":
//
//                  for(ARObject obj : markerInfo.getObjects()) {
////                        if(tmp.get)
//
//                  }
//
//                  actionName = null;
//                  performAction = false;
//                  break;
//          }
        }

        markerInfo.draw(gl);

        if (customRenderer != null) {
            customRenderer.draw(gl);
        }


        if (takeScreenshot) {
            Log.d("SCREENSHOT", "Sprawdzam touched");

            Ray r = new Ray(gl, screenWidth, screenHeight, x, y);
            Log.d("SCREENSHOT", "Near Coord =" + Arrays.toString(r.P0));
            Log.d("SCREENSHOT", "Far Coord =" + Arrays.toString(r.P1));

            takeScreenshot = false;
        }

    }

1 个答案:

答案 0 :(得分:0)

OpenGL是一个基于状态的绘图系统。在您进行绘图调用的那一刻,未激活/启用的状态无效。您正在启用颜色数组,设置指针,然后再次禁用它后立即。对于要考虑的颜色顶点数组,必须启用它。

但是你似乎也在那里使用纹理。最重要的是,您正在使用固定功能管道(FFP)。纹理,颜色和照明之间存在许多相互作用,这些相互作用都会导致颜色不显示或没有像您期望的那样出现。

帮自己一个忙,开始使用着色器。了解FFP的工作方式并不难;但是它增长了很多状态切换和数据路径,使用它变得非常麻烦。您可以根据需要编写40多行代码来设置FFP,也可以编写行着色器代码以达到同样的效果。