diff options
Diffstat (limited to 'opengl')
| -rw-r--r-- | opengl/libagl/array.cpp | 4 | ||||
| -rw-r--r-- | opengl/libagl/light.cpp | 35 | ||||
| -rw-r--r-- | opengl/libagl/matrix.cpp | 83 | ||||
| -rw-r--r-- | opengl/tests/lighting1709/Android.mk | 11 | ||||
| -rw-r--r-- | opengl/tests/lighting1709/AndroidManifest.xml | 13 | ||||
| -rw-r--r-- | opengl/tests/lighting1709/src/com/android/lightingtest/ClearActivity.java | 174 |
6 files changed, 242 insertions, 78 deletions
diff --git a/opengl/libagl/array.cpp b/opengl/libagl/array.cpp index 6d2cc9111c84..cffe880edd0d 100644 --- a/opengl/libagl/array.cpp +++ b/opengl/libagl/array.cpp @@ -960,6 +960,8 @@ void compileElement__generic(ogles_context_t* c, v->index = first; first &= vertex_cache_t::INDEX_MASK; const GLubyte* vp = c->arrays.vertex.element(first); + v->obj.z = 0; + v->obj.w = 0x10000; c->arrays.vertex.fetch(c, v->obj.v, vp); c->arrays.mvp_transform(&c->transforms.mvp, &v->clip, &v->obj); c->arrays.perspective(c, v); @@ -975,6 +977,8 @@ void compileElements__generic(ogles_context_t* c, do { v->flags = 0; v->index = first++; + v->obj.z = 0; + v->obj.w = 0x10000; c->arrays.vertex.fetch(c, v->obj.v, vp); c->arrays.mvp_transform(mvp, &v->clip, &v->obj); c->arrays.perspective(c, v); diff --git a/opengl/libagl/light.cpp b/opengl/libagl/light.cpp index 25c41d0c5b9d..8ae32cc0f0e1 100644 --- a/opengl/libagl/light.cpp +++ b/opengl/libagl/light.cpp @@ -38,13 +38,14 @@ static void lightVertex(ogles_context_t* c, vertex_t* v); static void lightVertexMaterial(ogles_context_t* c, vertex_t* v); static inline void vscale3(GLfixed* d, const GLfixed* m, GLfixed s); -static inline void vsub3w(GLfixed* d, const GLfixed* a, const GLfixed* b); static __attribute__((noinline)) void vnorm3(GLfixed* d, const GLfixed* a); static inline void vsa3(GLfixed* d, const GLfixed* m, GLfixed s, const GLfixed* a); +static inline void vss3(GLfixed* d, + const GLfixed* m, GLfixed s, const GLfixed* a); static inline void vmla3(GLfixed* d, const GLfixed* m0, const GLfixed* m1, const GLfixed* a); static inline void vmul3(GLfixed* d, @@ -151,18 +152,10 @@ void vsa3(GLfixed* d, const GLfixed* m, GLfixed s, const GLfixed* a) { } static inline -void vsub3w(GLfixed* d, const GLfixed* a, const GLfixed* b) { - const GLfixed wa = a[3]; - const GLfixed wb = b[3]; - if (ggl_likely(wa == wb)) { - d[0] = a[0] - b[0]; - d[1] = a[1] - b[1]; - d[2] = a[2] - b[2]; - } else { - d[0] = gglMulSubx(a[0], wb, gglMulx(b[0], wa)); - d[1] = gglMulSubx(a[1], wb, gglMulx(b[1], wa)); - d[2] = gglMulSubx(a[2], wb, gglMulx(b[2], wa)); - } +void vss3(GLfixed* d, const GLfixed* m, GLfixed s, const GLfixed* a) { + d[0] = gglMulSubx(m[0], s, a[0]); + d[1] = gglMulSubx(m[1], s, a[1]); + d[2] = gglMulSubx(m[2], s, a[2]); } static inline @@ -227,7 +220,7 @@ static inline void validate_light_mvi(ogles_context_t* c) const int i = 31 - gglClz(en); en &= ~(1<<i); light_t& l = c->lighting.lights[i]; - c->transforms.mvui.point3(&c->transforms.mvui, + c->transforms.mvui.point4(&c->transforms.mvui, &l.objPosition, &l.position); vnorm3(l.normalizedObjPosition.v, l.objPosition.v); } @@ -318,6 +311,11 @@ void lightVertexMaterial(ogles_context_t* c, vertex_t* v) vmul3(l.implicitAmbient.v, material.ambient.v, l.ambient.v); vmul3(l.implicitDiffuse.v, material.diffuse.v, l.diffuse.v); vmul3(l.implicitSpecular.v, material.specular.v, l.specular.v); + // this is just a flag to tell if we have a specular component + l.implicitSpecular.v[3] = + l.implicitSpecular.r | + l.implicitSpecular.g | + l.implicitSpecular.b; } // emission and ambient for the whole scene vmla3( c->lighting.implicitSceneEmissionAndAmbient.v, @@ -343,7 +341,11 @@ void lightVertex(ogles_context_t* c, vertex_t* v) vec4_t n; c->arrays.normal.fetch(c, n.v, c->arrays.normal.element(v->index & vertex_cache_t::INDEX_MASK)); - if (c->transforms.rescaleNormals == GL_NORMALIZE) + + // TODO: right now we handle GL_RESCALE_NORMALS as if ti were + // GL_NORMALIZE. We could optimize this by scaling mvui + // appropriately instead. + if (c->transforms.rescaleNormals) vnorm3(n.v, n.v); const material_t& material = c->lighting.front; @@ -360,7 +362,8 @@ void lightVertex(ogles_context_t* c, vertex_t* v) // compute vertex-to-light vector if (ggl_unlikely(l.position.w)) { - vsub3w(d.v, l.objPosition.v, v->obj.v); + // lightPos/1.0 - vertex/vertex.w == lightPos*vertex.w - vertex + vss3(d.v, l.objPosition.v, v->obj.w, v->obj.v); sqDist = dot3(d.v, d.v); vscale3(d.v, d.v, gglSqrtRecipx(sqDist)); } else { diff --git a/opengl/libagl/matrix.cpp b/opengl/libagl/matrix.cpp index f175cdad6e6a..0b68dc06f5e3 100644 --- a/opengl/libagl/matrix.cpp +++ b/opengl/libagl/matrix.cpp @@ -55,7 +55,7 @@ static void normal__nop(transform_t const*, vec4_t* c, vec4_t const* o); static void point2__generic(transform_t const*, vec4_t* c, vec4_t const* o); static void point3__generic(transform_t const*, vec4_t* c, vec4_t const* o); static void point4__generic(transform_t const*, vec4_t* c, vec4_t const* o); -static void normal__generic(transform_t const*, vec4_t* c, vec4_t const* o); +static void point4__mvui(transform_t const*, vec4_t* c, vec4_t const* o); // ---------------------------------------------------------------------------- #if 0 @@ -209,7 +209,8 @@ void mvui_transform_t::picker() { flags = 0; ops = OP_ALL; - point3 = normal__generic; + point3 = point4__mvui; + point4 = point4__mvui; } void transform_t::dump(const char* what) @@ -596,66 +597,19 @@ void transform_state_t::update_mvit() void transform_state_t::update_mvui() { + GLfloat r[16]; const GLfloat* const mv = modelview.top().elements(); - - /* - When transforming normals, we can use the upper 3x3 matrix, see: - http://www.opengl.org/documentation/specs/version1.1/glspec1.1/node26.html - */ - // Also note that: - // l(obj) = tr(M).l(eye) for infinite light - // l(obj) = inv(M).l(eye) for local light - - const uint32_t ops = modelview.top_ops() & ~OP_TRANSLATE; - if (ggl_likely((!(ops & ~OP_ROTATE)) || - (rescaleNormals && modelview.isRigidBody()))) { - // if the modelview matrix is a rigid body transformation - // (translation, rotation, uniform scaling), then we can bypass - // the inverse by transposing the matrix. - GLfloat rescale = 1.0f; - if (rescaleNormals == GL_RESCALE_NORMAL) { - if (!(ops & ~OP_UNIFORM_SCALE)) { - rescale = reciprocalf(mv[I(0,0)]); - } else { - rescale = rsqrtf( - sqrf(mv[I(2,0)]) + sqrf(mv[I(2,1)]) + sqrf(mv[I(2,2)])); - } - } - GLfixed* const x = mvui.matrix.m; - for (int i=0 ; i<3 ; i++) { - x[I(i,0)] = gglFloatToFixed(mv[I(0,i)] * rescale); - x[I(i,1)] = gglFloatToFixed(mv[I(1,i)] * rescale); - x[I(i,2)] = gglFloatToFixed(mv[I(2,i)] * rescale); - } - mvui.picker(); - return; - } - - GLfloat r[3][3]; - r[0][0] = det22(mv[I(1,1)], mv[I(2,1)], mv[I(1,2)], mv[I(2,2)]); - r[0][1] =ndet22(mv[I(0,1)], mv[I(2,1)], mv[I(0,2)], mv[I(2,2)]); - r[0][2] = det22(mv[I(0,1)], mv[I(1,1)], mv[I(0,2)], mv[I(1,2)]); - r[1][0] =ndet22(mv[I(1,0)], mv[I(2,0)], mv[I(1,2)], mv[I(2,2)]); - r[1][1] = det22(mv[I(0,0)], mv[I(2,0)], mv[I(0,2)], mv[I(2,2)]); - r[1][2] =ndet22(mv[I(0,0)], mv[I(1,0)], mv[I(0,2)], mv[I(1,2)]); - r[2][0] = det22(mv[I(1,0)], mv[I(2,0)], mv[I(1,1)], mv[I(2,1)]); - r[2][1] =ndet22(mv[I(0,0)], mv[I(2,0)], mv[I(0,1)], mv[I(2,1)]); - r[2][2] = det22(mv[I(0,0)], mv[I(1,0)], mv[I(0,1)], mv[I(1,1)]); - - GLfloat rdet; - if (rescaleNormals == GL_RESCALE_NORMAL) { - rdet = rsqrtf(sqrf(r[0][2]) + sqrf(r[1][2]) + sqrf(r[2][2])); - } else { - rdet = reciprocalf( - r[0][0]*mv[I(0,0)] + r[0][1]*mv[I(1,0)] + r[0][2]*mv[I(2,0)]); - } + // TODO: we need a faster invert, especially for when the modelview + // is a rigid-body matrix + invert(r, mv); GLfixed* const x = mvui.matrix.m; - for (int i=0 ; i<3 ; i++) { - x[I(i,0)] = gglFloatToFixed(r[i][0] * rdet); - x[I(i,1)] = gglFloatToFixed(r[i][1] * rdet); - x[I(i,2)] = gglFloatToFixed(r[i][2] * rdet); + for (int i=0 ; i<4 ; i++) { + x[I(i,0)] = gglFloatToFixed(r[I(i,0)]); + x[I(i,1)] = gglFloatToFixed(r[I(i,1)]); + x[I(i,2)] = gglFloatToFixed(r[I(i,2)]); + x[I(i,4)] = gglFloatToFixed(r[I(i,3)]); } mvui.picker(); } @@ -783,14 +737,19 @@ void point4__generic(transform_t const* mx, vec4_t* lhs, vec4_t const* rhs) { lhs->w = mla4(rx, m[ 3], ry, m[ 7], rz, m[11], rw, m[15]); } -void normal__generic(transform_t const* mx, vec4_t* lhs, vec4_t const* rhs) { +void point4__mvui(transform_t const* mx, vec4_t* lhs, vec4_t const* rhs) { + // this used for transforming light positions back to object space. + // Lights have 3 components positions, so w is always 1. + // however, it is used as a switch for directional lights, so we need + // to preserve it. const GLfixed* const m = mx->matrix.m; const GLfixed rx = rhs->x; const GLfixed ry = rhs->y; const GLfixed rz = rhs->z; - lhs->x = mla3(rx, m[ 0], ry, m[ 4], rz, m[ 8]); - lhs->y = mla3(rx, m[ 1], ry, m[ 5], rz, m[ 9]); - lhs->z = mla3(rx, m[ 2], ry, m[ 6], rz, m[10]); + lhs->x = mla3a(rx, m[ 0], ry, m[ 4], rz, m[ 8], m[12]); + lhs->y = mla3a(rx, m[ 1], ry, m[ 5], rz, m[ 9], m[13]); + lhs->z = mla3a(rx, m[ 2], ry, m[ 6], rz, m[10], m[14]); + lhs->w = rhs->w; } diff --git a/opengl/tests/lighting1709/Android.mk b/opengl/tests/lighting1709/Android.mk new file mode 100644 index 000000000000..9563e617f3aa --- /dev/null +++ b/opengl/tests/lighting1709/Android.mk @@ -0,0 +1,11 @@ +LOCAL_PATH:= $(call my-dir) +include $(CLEAR_VARS) + +LOCAL_MODULE_TAGS := tests + +LOCAL_SRC_FILES := $(call all-subdir-java-files) + +LOCAL_PACKAGE_NAME := LightingTest +LOCAL_CERTIFICATE := platform + +include $(BUILD_PACKAGE) diff --git a/opengl/tests/lighting1709/AndroidManifest.xml b/opengl/tests/lighting1709/AndroidManifest.xml new file mode 100644 index 000000000000..6c23d422f5ec --- /dev/null +++ b/opengl/tests/lighting1709/AndroidManifest.xml @@ -0,0 +1,13 @@ +<manifest xmlns:android="http://schemas.android.com/apk/res/android" + package="com.android.lightingtest"> + + <application> + <activity android:name="ClearActivity" android:label="LightingTest"> + <intent-filter> + <action android:name="android.intent.action.MAIN" /> + <category android:name="android.intent.category.DEFAULT" /> + <category android:name="android.intent.category.LAUNCHER" /> + </intent-filter> + </activity> + </application> +</manifest> diff --git a/opengl/tests/lighting1709/src/com/android/lightingtest/ClearActivity.java b/opengl/tests/lighting1709/src/com/android/lightingtest/ClearActivity.java new file mode 100644 index 000000000000..3ae8c5ca29d7 --- /dev/null +++ b/opengl/tests/lighting1709/src/com/android/lightingtest/ClearActivity.java @@ -0,0 +1,174 @@ +/* + * Copyright (C) 2007 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package com.android.lightingtest; + +import java.nio.ByteBuffer; +import java.nio.ByteOrder; +import java.nio.FloatBuffer; + +import javax.microedition.khronos.egl.EGL10; +import javax.microedition.khronos.egl.EGLConfig; +import javax.microedition.khronos.opengles.GL10; + +import android.app.Activity; +import android.content.Context; +import android.opengl.GLSurfaceView; +import android.os.Bundle; +import android.util.Log; +import android.view.MotionEvent; + +public class ClearActivity extends Activity { + @Override + protected void onCreate(Bundle savedInstanceState) { + super.onCreate(savedInstanceState); + mGLView = new ClearGLSurfaceView(this); + setContentView(mGLView); + } + + @Override + protected void onPause() { + super.onPause(); + mGLView.onPause(); + } + + @Override + protected void onResume() { + super.onResume(); + mGLView.onResume(); + } + private GLSurfaceView mGLView; +} + +class ClearGLSurfaceView extends GLSurfaceView { + public ClearGLSurfaceView(Context context) { + super(context); + mRenderer = new ClearRenderer(); + setRenderer(mRenderer); + } + + ClearRenderer mRenderer; +} + +class ClearRenderer implements GLSurfaceView.Renderer { + public ClearRenderer() { + } + + public void onSurfaceCreated(GL10 gl, EGLConfig config) { + // Do nothing special. + } + + public void onSurfaceChanged(GL10 gl, int w, int h) { + // Compute the projection matrix + gl.glMatrixMode(GL10.GL_PROJECTION); + gl.glLoadIdentity(); + + // Compute the boundaries of the frustum + float fl = (float) (-(w / 2)) / 288; + float fr = (float) (w / 2) / 288; + float ft = (float) (h / 2) / 288; + float fb = (float) (-(h / 2)) / 288; + + // Set the view frustum + gl.glFrustumf(fl, fr, fb, ft, 1.0f, 2000.0f); + + // Set the viewport dimensions + gl.glMatrixMode(GL10.GL_MODELVIEW); + gl.glLoadIdentity(); + gl.glViewport(0, 0, w, h); + } + + public void onDrawFrame(GL10 gl) { + gl.glClear(GL10.GL_COLOR_BUFFER_BIT | GL10.GL_DEPTH_BUFFER_BIT); + + final float lightOff[] = {0.0f, 0.0f, 0.0f, 1.0f}; + final float lightAmbient[] = {5.0f, 0.0f, 0.0f, 1.0f}; + final float lightDiffuse[] = {0.0f, 2.0f, 0.0f, 0.0f}; + final float lightPosSpot[] = {0.0f, 0.0f, -8.0f, 1.0f}; + + final float pos[] = { + -5.0f, -1.5f, 0.0f, + 0.0f, -1.5f, 0.0f, + 5.0f, -1.5f, 0.0f, + }; + + final float v[] = new float[9]; + ByteBuffer vbb = ByteBuffer.allocateDirect(v.length*4); + vbb.order(ByteOrder.nativeOrder()); + FloatBuffer vb = vbb.asFloatBuffer(); + + gl.glDisable(GL10.GL_DITHER); + + gl.glLightfv(GL10.GL_LIGHT0, GL10.GL_AMBIENT, lightAmbient, 0); + gl.glLightfv(GL10.GL_LIGHT0, GL10.GL_DIFFUSE, lightDiffuse, 0); + gl.glLightfv(GL10.GL_LIGHT0, GL10.GL_SPECULAR, lightOff, 0); + gl.glLightfv(GL10.GL_LIGHT0, GL10.GL_POSITION, lightPosSpot, 0); + gl.glEnable(GL10.GL_LIGHT0); + + gl.glEnable(GL10.GL_LIGHTING); + + + gl.glEnableClientState(GL10.GL_VERTEX_ARRAY); + gl.glNormal3f(0, 0, 1); + + + // draw first 3 triangles, without using transforms + for (int i=0 ; i<3 ; i++) { + v[0] = -1; v[1] =-1; v[2] = -10; + v[3] = 0; v[4] = 1; v[5] = -10; + v[6] = 1; v[7] =-1; v[8] = -10; + for (int j=0 ; j<3 ; j++) { + v[j*3+0] -= pos[i*3+0]; + v[j*3+1] -= pos[i*3+1]; + v[j*3+2] -= pos[i*3+2]; + } + vb.put(v).position(0); + gl.glVertexPointer(3, GL10.GL_FLOAT, 0, vb); + gl.glDrawArrays(GL10.GL_TRIANGLE_STRIP, 0, 3); + } + + // draw the 2nd batch this time with transforms + v[0] = -1; v[1] =-1; v[2] = -10; + v[3] = 0; v[4] = 1; v[5] = -10; + v[6] = 1; v[7] =-1; v[8] = -10; + vb.put(v).position(0); + gl.glVertexPointer(3, GL10.GL_FLOAT, 0, vb); + + // draw lower left triangle + gl.glPushMatrix(); + gl.glTranslatef(pos[0], pos[1], pos[2]); + gl.glDrawArrays(GL10.GL_TRIANGLE_STRIP, 0, 3); + gl.glPopMatrix(); + + // draw lower middle triangle + gl.glPushMatrix(); + gl.glTranslatef(pos[3], pos[4], pos[5]); + gl.glDrawArrays(GL10.GL_TRIANGLE_STRIP, 0, 3); + gl.glPopMatrix(); + + // draw lower right triangle + gl.glPushMatrix(); + gl.glTranslatef(pos[6], pos[7], pos[8]); + gl.glDrawArrays(GL10.GL_TRIANGLE_STRIP, 0, 3); + gl.glPopMatrix(); + } + + public int[] getConfigSpec() { + int[] configSpec = { EGL10.EGL_DEPTH_SIZE, 16, EGL10.EGL_NONE }; + return configSpec; + } +} + |