diff options
-rw-r--r-- | graphics/java/android/renderscript/Program.java | 43 | ||||
-rw-r--r-- | graphics/java/android/renderscript/ProgramVertex.java | 10 | ||||
-rw-r--r-- | libs/rs/java/Samples/res/raw/shaderf.glsl | 18 | ||||
-rw-r--r-- | libs/rs/java/Samples/res/raw/shaderv.glsl | 42 | ||||
-rw-r--r-- | libs/rs/java/Samples/res/raw/torus.a3d | bin | 37476 -> 571236 bytes | |||
-rw-r--r-- | libs/rs/java/Samples/src/com/android/samples/RsRenderStatesRS.java | 44 | ||||
-rw-r--r-- | libs/rs/java/Samples/src/com/android/samples/rsrenderstates.rs | 106 | ||||
-rw-r--r-- | libs/rs/java/Samples/src/com/android/samples/shader_def.rsh | 47 | ||||
-rw-r--r-- | libs/rs/rsProgramVertex.cpp | 90 | ||||
-rw-r--r-- | libs/rs/rsVertexArray.cpp | 5 |
10 files changed, 362 insertions, 43 deletions
diff --git a/graphics/java/android/renderscript/Program.java b/graphics/java/android/renderscript/Program.java index 1628a97..c6ed72a 100644 --- a/graphics/java/android/renderscript/Program.java +++ b/graphics/java/android/renderscript/Program.java @@ -17,6 +17,11 @@ package android.renderscript; +import java.io.IOException; +import java.io.InputStream; +import java.io.UnsupportedEncodingException; + +import android.content.res.Resources; import android.util.Config; import android.util.Log; @@ -95,6 +100,44 @@ public class Program extends BaseObj { return this; } + public BaseProgramBuilder setShader(Resources resources, int resourceID) { + byte[] str; + int strLength; + InputStream is = resources.openRawResource(resourceID); + try { + try { + str = new byte[1024]; + strLength = 0; + while(true) { + int bytesLeft = str.length - strLength; + if (bytesLeft == 0) { + byte[] buf2 = new byte[str.length * 2]; + System.arraycopy(str, 0, buf2, 0, str.length); + str = buf2; + bytesLeft = str.length - strLength; + } + int bytesRead = is.read(str, strLength, bytesLeft); + if (bytesRead <= 0) { + break; + } + strLength += bytesRead; + } + } finally { + is.close(); + } + } catch(IOException e) { + throw new Resources.NotFoundException(); + } + + try { + mShader = new String(str, 0, strLength, "UTF-8"); + } catch (UnsupportedEncodingException e) { + Log.e("Renderscript shader creation", "Could not decode shader string"); + } + + return this; + } + public void addInput(Element e) throws IllegalStateException { // Should check for consistant and non-conflicting names... if(mInputCount >= MAX_INPUT) { diff --git a/graphics/java/android/renderscript/ProgramVertex.java b/graphics/java/android/renderscript/ProgramVertex.java index c99efd6..b072433 100644 --- a/graphics/java/android/renderscript/ProgramVertex.java +++ b/graphics/java/android/renderscript/ProgramVertex.java @@ -107,14 +107,10 @@ public class ProgramVertex extends Program { public Allocation mAlloc; public MatrixAllocation(RenderScript rs) { - mModel = new Matrix4f(); - mProjection = new Matrix4f(); - mTexture = new Matrix4f(); - mAlloc = Allocation.createSized(rs, Element.createUser(rs, Element.DataType.FLOAT_32), 48); - mAlloc.subData1D(MODELVIEW_OFFSET, 16, mModel.mMat); - mAlloc.subData1D(PROJECTION_OFFSET, 16, mProjection.mMat); - mAlloc.subData1D(TEXTURE_OFFSET, 16, mTexture.mMat); + loadModelview(new Matrix4f()); + loadProjection(new Matrix4f()); + loadTexture(new Matrix4f()); } public void destroy() { diff --git a/libs/rs/java/Samples/res/raw/shaderf.glsl b/libs/rs/java/Samples/res/raw/shaderf.glsl new file mode 100644 index 0000000..81452ab --- /dev/null +++ b/libs/rs/java/Samples/res/raw/shaderf.glsl @@ -0,0 +1,18 @@ + +varying lowp float light0_Diffuse; +varying lowp float light0_Specular; +varying lowp float light1_Diffuse; +varying lowp float light1_Specular; + +void main() { + vec2 t0 = varTex0.xy; + lowp vec4 col = texture2D(uni_Tex0, t0).rgba; + /*col = col * (light0_Diffuse * UNI_light0_DiffuseColor + light1_Diffuse * UNI_light1_DiffuseColor); + col += light0_Specular * UNI_light0_SpecularColor; + col += light1_Specular * UNI_light1_SpecularColor;*/ + col = col * (light0_Diffuse + light1_Diffuse); + col += light0_Specular; + col += light1_Specular; + gl_FragColor = col; +} + diff --git a/libs/rs/java/Samples/res/raw/shaderv.glsl b/libs/rs/java/Samples/res/raw/shaderv.glsl new file mode 100644 index 0000000..7f61197 --- /dev/null +++ b/libs/rs/java/Samples/res/raw/shaderv.glsl @@ -0,0 +1,42 @@ +varying float light0_Diffuse; +varying float light0_Specular; +varying float light1_Diffuse; +varying float light1_Specular; + +/* +rs_matrix4x4 model; + float3 light0_Posision; + float light0_Diffuse; + float light0_Specular; + float light0_CosinePower; + + float3 light1_Posision; + float light1_Diffuse; + float light1_Specular; + float light1_CosinePower; +*/ + +// This is where actual shader code begins +void main() { + vec4 worldPos = UNI_model * ATTRIB_position; + gl_Position = UNI_MVP * worldPos; + + mat3 model3 = mat3(UNI_model[0].xyz, UNI_model[1].xyz, UNI_model[2].xyz); + vec3 worldNorm = model3 * ATTRIB_normal; + vec3 V = normalize(-worldPos.xyz); + + vec3 light0Vec = normalize(UNI_light0_Posision - worldPos.xyz); + vec3 light0R = reflect(light0Vec, worldNorm); + light0_Diffuse = clamp(dot(worldNorm, light0Vec), 0.0, 1.0) * UNI_light0_Diffuse; + float light0Spec = clamp(dot(light0R, V), 0.001, 1.0); + light0_Specular = pow(light0Spec, UNI_light0_CosinePower) * UNI_light0_Specular; + + vec3 light1Vec = normalize(UNI_light1_Posision - worldPos.xyz); + vec3 light1R = reflect(light1Vec, worldNorm); + light1_Diffuse = clamp(dot(worldNorm, light1Vec), 0.0, 1.0) * UNI_light1_Diffuse; + float light1Spec = clamp(dot(light1R, V), 0.001, 1.0); + light1_Specular = pow(light1Spec, UNI_light1_CosinePower) * UNI_light1_Specular; + + gl_PointSize = 1.0; + varTex0 = ATTRIB_texture0; +} diff --git a/libs/rs/java/Samples/res/raw/torus.a3d b/libs/rs/java/Samples/res/raw/torus.a3d Binary files differindex 610f095..d09bc13 100644 --- a/libs/rs/java/Samples/res/raw/torus.a3d +++ b/libs/rs/java/Samples/res/raw/torus.a3d diff --git a/libs/rs/java/Samples/src/com/android/samples/RsRenderStatesRS.java b/libs/rs/java/Samples/src/com/android/samples/RsRenderStatesRS.java index 8eff455..e76e740 100644 --- a/libs/rs/java/Samples/src/com/android/samples/RsRenderStatesRS.java +++ b/libs/rs/java/Samples/src/com/android/samples/RsRenderStatesRS.java @@ -65,6 +65,13 @@ public class RsRenderStatesRS { private ProgramVertex mProgVertex; private ProgramVertex.MatrixAllocation mPVA; + // Custom shaders + private ProgramVertex mProgVertexCustom; + private ProgramVertex.MatrixAllocation mPVACustom; + private ProgramFragment mProgFragmentCustom; + private ScriptField_VertexShaderConstants_s mVSConst; + private ScriptField_FragentShaderConstants_s mFSConst; + private ProgramRaster mCullBack; private ProgramRaster mCullFront; @@ -178,6 +185,42 @@ public class RsRenderStatesRS { mScript.set_gProgVertex(mProgVertex); } + private void initCustomShaders() { + mVSConst = new ScriptField_VertexShaderConstants_s(mRS, 1); + mFSConst = new ScriptField_FragentShaderConstants_s(mRS, 1); + + mScript.bind_gVSConstants(mVSConst); + mScript.bind_gFSConstants(mFSConst); + + // Initialize the shader builder + ProgramVertex.ShaderBuilder pvbCustom = new ProgramVertex.ShaderBuilder(mRS); + // Specify the resource that contains the shader string + pvbCustom.setShader(mRes, R.raw.shaderv); + // Use a script field to spcify the input layout + pvbCustom.addInput(ScriptField_VertexShaderInputs_s.createElement(mRS)); + // Define the constant input layout + pvbCustom.addConstant(mVSConst.getAllocation().getType()); + mProgVertexCustom = pvbCustom.create(); + // Bind the source of constant data + mProgVertexCustom.bindConstants(mVSConst.getAllocation(), 1); + mPVACustom = new ProgramVertex.MatrixAllocation(mRS); + mProgVertexCustom.bindAllocation(mPVACustom); + + ProgramFragment.ShaderBuilder pfbCustom = new ProgramFragment.ShaderBuilder(mRS); + // Specify the resource that contains the shader string + pfbCustom.setShader(mRes, R.raw.shaderf); + //Tell the builder how many textures we have + pfbCustom.setTextureCount(1); + // Define the constant input layout + pfbCustom.addConstant(mFSConst.getAllocation().getType()); + mProgFragmentCustom = pfbCustom.create(); + // Bind the source of constant data + mProgFragmentCustom.bindConstants(mFSConst.getAllocation(), 1); + + mScript.set_gProgVertexCustom(mProgVertexCustom); + mScript.set_gProgFragmentCustom(mProgFragmentCustom); + } + private Allocation loadTextureRGB(int id) { final Allocation allocation = Allocation.createFromBitmapResource(mRS, mRes, id, Element.RGB_565(mRS), true); @@ -274,6 +317,7 @@ public class RsRenderStatesRS { loadImages(); initMesh(); initProgramRaster(); + initCustomShaders(); mRS.contextBindRootScript(mScript); } diff --git a/libs/rs/java/Samples/src/com/android/samples/rsrenderstates.rs b/libs/rs/java/Samples/src/com/android/samples/rsrenderstates.rs index 68d9d3c..165a6d7 100644 --- a/libs/rs/java/Samples/src/com/android/samples/rsrenderstates.rs +++ b/libs/rs/java/Samples/src/com/android/samples/rsrenderstates.rs @@ -17,6 +17,7 @@ #pragma rs java_package_name(com.android.samples) #include "rs_graphics.rsh" +#include "shader_def.rsh" rs_program_vertex gProgVertex; rs_program_fragment gProgFragmentColor; @@ -51,6 +52,15 @@ rs_sampler gNearestClamp; rs_program_raster gCullBack; rs_program_raster gCullFront; +// Custom vertex shader compunents +VertexShaderConstants *gVSConstants; +FragentShaderConstants *gFSConstants; +// Export these out to easily set the inputs to shader +VertexShaderInputs *gVSInputs; +// Custom shaders we use for lighting +rs_program_vertex gProgVertexCustom; +rs_program_fragment gProgFragmentCustom; + #pragma rs export_var(gProgVertex, gProgFragmentColor, gProgFragmentTexture) #pragma rs export_var(gProgStoreBlendNoneDepth, gProgStoreBlendNone, gProgStoreBlendAlpha, gProgStoreBlendAdd) #pragma rs export_var(gTexOpaque, gTexTorus, gTexTransparent) @@ -58,6 +68,7 @@ rs_program_raster gCullFront; #pragma rs export_var(gFontSans, gFontSerif, gFontSerifBold, gFontSerifItalic, gFontSerifBoldItalic, gFontMono) #pragma rs export_var(gLinearClamp, gLinearWrap, gMipLinearWrap, gNearestClamp) #pragma rs export_var(gCullBack, gCullFront) +#pragma rs export_var(gVSConstants, gFSConstants, gVSInputs, gProgVertexCustom, gProgFragmentCustom) //What we are showing #pragma rs export_var(gDisplayMode) @@ -274,7 +285,7 @@ void displayTextureSamplers() { float gTorusRotation = 0; -void displayCullingSamplers() { +void displayCullingSamples() { rsgBindProgramVertex(gProgVertex); // Setup the projectioni matrix with 60 degree field of view rs_matrix4x4 proj; @@ -315,6 +326,94 @@ void displayCullingSamplers() { rsgDrawText("Displaying mesh front/back face culling", 10, rsgGetHeight() - 10); } +float gLight0Rotation = 0; +float gLight1Rotation = 0; + +void setupCustomShaderLights() { + float4 light0Pos = {-5.0f, 5.0f, -10.0f, 1.0f}; + float4 light1Pos = {2.0f, 5.0f, 15.0f, 1.0f}; + float3 light0DiffCol = {0.9f, 0.7f, 0.7f}; + float3 light0SpecCol = {0.9f, 0.8f, 0.8f}; + float3 light1DiffCol = {0.7f, 0.7f, 0.9f}; + float3 light1SpecCol = {0.8f, 0.8f, 0.9f}; + + gLight0Rotation += 150.0f * rsGetDt(); + if(gLight0Rotation > 360.0f) { + gLight0Rotation -= 360.0f; + } + gLight1Rotation -= 50.0f * rsGetDt(); + if(gLight1Rotation > 360.0f) { + gLight1Rotation -= 360.0f; + } + + rs_matrix4x4 l0Mat; + rsMatrixLoadRotate(&l0Mat, gLight0Rotation, 1.0f, 0.0f, 0.0f); + light0Pos = rsMatrixMultiply(&l0Mat, light0Pos); + rs_matrix4x4 l1Mat; + rsMatrixLoadRotate(&l1Mat, gLight1Rotation, 0.0f, 0.0f, 1.0f); + light1Pos = rsMatrixMultiply(&l1Mat, light1Pos); + + // Set light 0 properties + gVSConstants->light0_Posision.x = light0Pos.x; + gVSConstants->light0_Posision.y = light0Pos.y; + gVSConstants->light0_Posision.z = light0Pos.z; + gVSConstants->light0_Diffuse = 1.0f; + gVSConstants->light0_Specular = 0.5f; + gVSConstants->light0_CosinePower = 70.0f; + // Set light 1 properties + gVSConstants->light1_Posision.x = light1Pos.x; + gVSConstants->light1_Posision.y = light1Pos.y; + gVSConstants->light1_Posision.z = light1Pos.z; + gVSConstants->light1_Diffuse = 1.0f; + gVSConstants->light1_Specular = 0.7f; + gVSConstants->light1_CosinePower = 50.0f; + + // Update fragmetn shader constants + // Set light 0 colors + gFSConstants->light0_DiffuseColor = light0DiffCol; + gFSConstants->light0_SpecularColor = light0SpecCol; + // Set light 1 colors + gFSConstants->light1_DiffuseColor = light1DiffCol; + gFSConstants->light1_SpecularColor = light1SpecCol; +} + +void displayCustomShaderSamples() { + + // Update vertex shader constants + // Load model matrix + // Aplly a rotation to our mesh + gTorusRotation += 50.0f * rsGetDt(); + if(gTorusRotation > 360.0f) { + gTorusRotation -= 360.0f; + } + + // Position our model on the screen + rsMatrixLoadTranslate(&gVSConstants->model, 0.0f, 0.0f, -10.0f); + rsMatrixRotate(&gVSConstants->model, gTorusRotation, 1.0f, 0.0f, 0.0f); + setupCustomShaderLights(); + + rsgBindProgramVertex(gProgVertexCustom); + // Setup the projectioni matrix with 60 degree field of view + rs_matrix4x4 proj; + float aspect = (float)rsgGetWidth() / (float)rsgGetHeight(); + rsMatrixLoadPerspective(&proj, 30.0f, aspect, 0.1f, 100.0f); + rsgProgramVertexLoadProjectionMatrix(&proj); + + // Fragment shader with texture + rsgBindProgramStore(gProgStoreBlendNoneDepth); + rsgBindProgramFragment(gProgFragmentCustom); + rsgBindSampler(gProgFragmentCustom, 0, gLinearClamp); + rsgBindTexture(gProgFragmentCustom, 0, gTexTorus); + + // Use back face culling + rsgBindProgramRaster(gCullBack); + rsgDrawMesh(gTorusMesh); + + rsgFontColor(1.0f, 1.0f, 1.0f, 1.0f); + rsgBindFont(gFontMono); + rsgDrawText("Custom shader sample", 10, rsgGetHeight() - 10); +} + int root(int launchID) { rsgClearColor(0.2f, 0.2f, 0.2f, 0.0f); @@ -337,7 +436,10 @@ int root(int launchID) { displayTextureSamplers(); break; case 5: - displayCullingSamplers(); + displayCullingSamples(); + break; + case 6: + displayCustomShaderSamples(); break; } diff --git a/libs/rs/java/Samples/src/com/android/samples/shader_def.rsh b/libs/rs/java/Samples/src/com/android/samples/shader_def.rsh new file mode 100644 index 0000000..1b697ca --- /dev/null +++ b/libs/rs/java/Samples/src/com/android/samples/shader_def.rsh @@ -0,0 +1,47 @@ +// Copyright (C) 2009 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. + +#pragma version(1) + +#pragma rs java_package_name(com.android.samples) + +typedef struct VertexShaderConstants_s { + rs_matrix4x4 model; + float3 light0_Posision; + float light0_Diffuse; + float light0_Specular; + float light0_CosinePower; + + float3 light1_Posision; + float light1_Diffuse; + float light1_Specular; + float light1_CosinePower; + +} VertexShaderConstants; + +typedef struct FragentShaderConstants_s { + float3 light0_DiffuseColor; + float3 light0_SpecularColor; + + float3 light1_DiffuseColor; + float3 light1_SpecularColor; + +} FragentShaderConstants; + +typedef struct VertexShaderInputs_s { + float4 position; + float3 normal; + float4 texture0; +} VertexShaderInputs; + diff --git a/libs/rs/rsProgramVertex.cpp b/libs/rs/rsProgramVertex.cpp index aee4133..8468e26 100644 --- a/libs/rs/rsProgramVertex.cpp +++ b/libs/rs/rsProgramVertex.cpp @@ -146,13 +146,24 @@ void ProgramVertex::createShader() // Cannot be complex rsAssert(!f->getFieldCount()); - switch(f->getComponent().getVectorSize()) { - case 1: mShader.append("uniform float UNI_"); break; - case 2: mShader.append("uniform vec2 UNI_"); break; - case 3: mShader.append("uniform vec3 UNI_"); break; - case 4: mShader.append("uniform vec4 UNI_"); break; - default: - rsAssert(0); + if(f->getType() == RS_TYPE_MATRIX_4X4) { + mShader.append("uniform mat4 UNI_"); + } + else if(f->getType() == RS_TYPE_MATRIX_3X3) { + mShader.append("uniform mat3 UNI_"); + } + else if(f->getType() == RS_TYPE_MATRIX_2X2) { + mShader.append("uniform mat2 UNI_"); + } + else { + switch(f->getComponent().getVectorSize()) { + case 1: mShader.append("uniform float UNI_"); break; + case 2: mShader.append("uniform vec2 UNI_"); break; + case 3: mShader.append("uniform vec3 UNI_"); break; + case 4: mShader.append("uniform vec4 UNI_"); break; + default: + rsAssert(0); + } } mShader.append(fn); @@ -250,41 +261,53 @@ void ProgramVertex::setupGL2(const Context *rsc, ProgramVertexState *state, Shad const Element *f = e->getField(field); uint32_t offset = e->getFieldOffsetBytes(field); int32_t slot = sc->vtxUniformSlot(uidx); + const char *fieldName = e->getFieldName(field); const float *fd = reinterpret_cast<const float *>(&data[offset]); - //LOGE("Uniform slot=%i, offset=%i, constant=%i, field=%i, uidx=%i", slot, offset, ct, field, uidx); + // If this field is padding, skip it + if(fieldName[0] == '#') { + continue; + } + + //LOGE("Uniform slot=%i, offset=%i, constant=%i, field=%i, uidx=%i, name=%s", slot, offset, ct, field, uidx, fieldName); if (slot >= 0) { - switch(f->getComponent().getVectorSize()) { - case 1: - //LOGE("Uniform 1 = %f", fd[0]); - glUniform1fv(slot, 1, fd); - break; - case 2: - //LOGE("Uniform 2 = %f %f", fd[0], fd[1]); - glUniform2fv(slot, 1, fd); - break; - case 3: - //LOGE("Uniform 3 = %f %f %f", fd[0], fd[1], fd[2]); - glUniform3fv(slot, 1, fd); - break; - case 4: - //LOGE("Uniform 4 = %f %f %f %f", fd[0], fd[1], fd[2], fd[3]); - glUniform4fv(slot, 1, fd); - break; - default: - rsAssert(0); + if(f->getType() == RS_TYPE_MATRIX_4X4) { + glUniformMatrix4fv(slot, 1, GL_FALSE, fd); + } + else if(f->getType() == RS_TYPE_MATRIX_3X3) { + glUniformMatrix3fv(slot, 1, GL_FALSE, fd); + } + else if(f->getType() == RS_TYPE_MATRIX_2X2) { + glUniformMatrix2fv(slot, 1, GL_FALSE, fd); + } + else { + switch(f->getComponent().getVectorSize()) { + case 1: + //LOGE("Uniform 1 = %f", fd[0]); + glUniform1fv(slot, 1, fd); + break; + case 2: + //LOGE("Uniform 2 = %f %f", fd[0], fd[1]); + glUniform2fv(slot, 1, fd); + break; + case 3: + //LOGE("Uniform 3 = %f %f %f", fd[0], fd[1], fd[2]); + glUniform3fv(slot, 1, fd); + break; + case 4: + //LOGE("Uniform 4 = %f %f %f %f", fd[0], fd[1], fd[2], fd[3]); + glUniform4fv(slot, 1, fd); + break; + default: + rsAssert(0); + } } } uidx ++; } } - for (uint32_t ct=0; ct < mConstantCount; ct++) { - uint32_t glSlot = sc->vtxUniformSlot(ct + 1); - - } - state->mLast.set(this); rsc->checkError("ProgramVertex::setupGL2"); } @@ -340,7 +363,8 @@ void ProgramVertex::initAddUserElement(const Element *e, String8 *names, uint32_ const Element *ce = e->getField(ct); if (ce->getFieldCount()) { initAddUserElement(ce, names, count, prefix); - } else { + } + else if(e->getFieldName(ct)[0] != '#') { String8 tmp(prefix); tmp.append(e->getFieldName(ct)); names[*count].setTo(tmp.string()); diff --git a/libs/rs/rsVertexArray.cpp b/libs/rs/rsVertexArray.cpp index 001927c..075a70d 100644 --- a/libs/rs/rsVertexArray.cpp +++ b/libs/rs/rsVertexArray.cpp @@ -129,7 +129,7 @@ void VertexArray::setupGL2(const Context *rsc, class VertexArrayState *state, Sh rsc->checkError("VertexArray::setupGL2 disabled"); for (uint32_t ct=0; ct < mCount; ct++) { - uint32_t slot = 0; + int32_t slot = 0; if (mAttribs[ct].name[0] == '#') { continue; @@ -150,6 +150,9 @@ void VertexArray::setupGL2(const Context *rsc, class VertexArrayState *state, Sh continue; } } + if(slot < 0) { + continue; + } //logAttrib(ct, slot); glEnableVertexAttribArray(slot); |