Commit 729a9db9 authored by Gaëtan Renaudeau's avatar Gaëtan Renaudeau

Implement Array uniforms support

parent 60390631
......@@ -12,10 +12,7 @@
<option name="SELECTED_TEST_ARTIFACT" value="_android_test_" />
<option name="ASSEMBLE_TASK_NAME" value="assembleDebug" />
<option name="COMPILE_JAVA_TASK_NAME" value="compileDebugSources" />
<option name="ASSEMBLE_TEST_TASK_NAME" value="assembleDebugAndroidTest" />
<option name="COMPILE_JAVA_TEST_TASK_NAME" value="compileDebugAndroidTestSources" />
<afterSyncTasks>
<task>generateDebugAndroidTestSources</task>
<task>generateDebugSources</task>
</afterSyncTasks>
<option name="ALLOW_USER_CONFIGURATION" value="false" />
......@@ -29,7 +26,7 @@
</component>
<component name="NewModuleRootManager" LANGUAGE_LEVEL="JDK_1_7" inherit-compiler-output="false">
<output url="file://$MODULE_DIR$/build/intermediates/classes/debug" />
<output-test url="file://$MODULE_DIR$/build/intermediates/classes/androidTest/debug" />
<output-test url="file://$MODULE_DIR$/build/intermediates/classes/test/debug" />
<exclude-output />
<content url="file://$MODULE_DIR$">
<sourceFolder url="file://$MODULE_DIR$/build/generated/source/r/debug" isTestSource="false" generated="true" />
......@@ -51,6 +48,15 @@
<sourceFolder url="file://$MODULE_DIR$/src/debug/java" isTestSource="false" />
<sourceFolder url="file://$MODULE_DIR$/src/debug/jni" isTestSource="false" />
<sourceFolder url="file://$MODULE_DIR$/src/debug/rs" isTestSource="false" />
<sourceFolder url="file://$MODULE_DIR$/src/debug/shaders" isTestSource="false" />
<sourceFolder url="file://$MODULE_DIR$/src/testDebug/res" type="java-test-resource" />
<sourceFolder url="file://$MODULE_DIR$/src/testDebug/resources" type="java-test-resource" />
<sourceFolder url="file://$MODULE_DIR$/src/testDebug/assets" type="java-test-resource" />
<sourceFolder url="file://$MODULE_DIR$/src/testDebug/aidl" isTestSource="true" />
<sourceFolder url="file://$MODULE_DIR$/src/testDebug/java" isTestSource="true" />
<sourceFolder url="file://$MODULE_DIR$/src/testDebug/jni" isTestSource="true" />
<sourceFolder url="file://$MODULE_DIR$/src/testDebug/rs" isTestSource="true" />
<sourceFolder url="file://$MODULE_DIR$/src/testDebug/shaders" isTestSource="true" />
<sourceFolder url="file://$MODULE_DIR$/src/main/res" type="java-resource" />
<sourceFolder url="file://$MODULE_DIR$/src/main/resources" type="java-resource" />
<sourceFolder url="file://$MODULE_DIR$/src/main/assets" type="java-resource" />
......@@ -58,6 +64,15 @@
<sourceFolder url="file://$MODULE_DIR$/src/main/java" isTestSource="false" />
<sourceFolder url="file://$MODULE_DIR$/src/main/jni" isTestSource="false" />
<sourceFolder url="file://$MODULE_DIR$/src/main/rs" isTestSource="false" />
<sourceFolder url="file://$MODULE_DIR$/src/main/shaders" isTestSource="false" />
<sourceFolder url="file://$MODULE_DIR$/src/test/res" type="java-test-resource" />
<sourceFolder url="file://$MODULE_DIR$/src/test/resources" type="java-test-resource" />
<sourceFolder url="file://$MODULE_DIR$/src/test/assets" type="java-test-resource" />
<sourceFolder url="file://$MODULE_DIR$/src/test/aidl" isTestSource="true" />
<sourceFolder url="file://$MODULE_DIR$/src/test/java" isTestSource="true" />
<sourceFolder url="file://$MODULE_DIR$/src/test/jni" isTestSource="true" />
<sourceFolder url="file://$MODULE_DIR$/src/test/rs" isTestSource="true" />
<sourceFolder url="file://$MODULE_DIR$/src/test/shaders" isTestSource="true" />
<sourceFolder url="file://$MODULE_DIR$/src/androidTest/res" type="java-test-resource" />
<sourceFolder url="file://$MODULE_DIR$/src/androidTest/resources" type="java-test-resource" />
<sourceFolder url="file://$MODULE_DIR$/src/androidTest/assets" type="java-test-resource" />
......@@ -65,17 +80,31 @@
<sourceFolder url="file://$MODULE_DIR$/src/androidTest/java" isTestSource="true" />
<sourceFolder url="file://$MODULE_DIR$/src/androidTest/jni" isTestSource="true" />
<sourceFolder url="file://$MODULE_DIR$/src/androidTest/rs" isTestSource="true" />
<sourceFolder url="file://$MODULE_DIR$/src/androidTest/shaders" isTestSource="true" />
<excludeFolder url="file://$MODULE_DIR$/build/intermediates/annotations" />
<excludeFolder url="file://$MODULE_DIR$/build/intermediates/assets" />
<excludeFolder url="file://$MODULE_DIR$/build/intermediates/blame" />
<excludeFolder url="file://$MODULE_DIR$/build/intermediates/bundles" />
<excludeFolder url="file://$MODULE_DIR$/build/intermediates/classes" />
<excludeFolder url="file://$MODULE_DIR$/build/intermediates/dependency-cache" />
<excludeFolder url="file://$MODULE_DIR$/build/intermediates/exploded-aar/com.android.support/appcompat-v7/23.0.1/jars" />
<excludeFolder url="file://$MODULE_DIR$/build/intermediates/exploded-aar/com.android.support/recyclerview-v7/23.0.1/jars" />
<excludeFolder url="file://$MODULE_DIR$/build/intermediates/exploded-aar/com.android.support/support-v4/23.0.1/jars" />
<excludeFolder url="file://$MODULE_DIR$/build/intermediates/exploded-aar/com.facebook.fresco/drawee/0.8.1/jars" />
<excludeFolder url="file://$MODULE_DIR$/build/intermediates/exploded-aar/com.facebook.fresco/fbcore/0.8.1/jars" />
<excludeFolder url="file://$MODULE_DIR$/build/intermediates/exploded-aar/com.facebook.fresco/fresco/0.8.1/jars" />
<excludeFolder url="file://$MODULE_DIR$/build/intermediates/exploded-aar/com.facebook.fresco/imagepipeline-okhttp/0.8.1/jars" />
<excludeFolder url="file://$MODULE_DIR$/build/intermediates/exploded-aar/com.facebook.fresco/imagepipeline/0.8.1/jars" />
<excludeFolder url="file://$MODULE_DIR$/build/intermediates/exploded-aar/com.facebook.react/react-native/0.20.1/jars" />
<excludeFolder url="file://$MODULE_DIR$/build/intermediates/incremental" />
<excludeFolder url="file://$MODULE_DIR$/build/intermediates/incremental-safeguard" />
<excludeFolder url="file://$MODULE_DIR$/build/intermediates/jniLibs" />
<excludeFolder url="file://$MODULE_DIR$/build/intermediates/lint" />
<excludeFolder url="file://$MODULE_DIR$/build/intermediates/res" />
<excludeFolder url="file://$MODULE_DIR$/build/intermediates/rs" />
<excludeFolder url="file://$MODULE_DIR$/build/intermediates/shaders" />
<excludeFolder url="file://$MODULE_DIR$/build/intermediates/symbols" />
<excludeFolder url="file://$MODULE_DIR$/build/intermediates/transforms" />
<excludeFolder url="file://$MODULE_DIR$/build/outputs" />
<excludeFolder url="file://$MODULE_DIR$/build/tmp" />
</content>
......@@ -86,8 +115,8 @@
<orderEntry type="library" exported="" name="okio-1.6.0" level="project" />
<orderEntry type="library" exported="" name="stetho-okhttp-1.2.0" level="project" />
<orderEntry type="library" exported="" name="okhttp-2.5.0" level="project" />
<orderEntry type="library" exported="" name="stetho-1.2.0" level="project" />
<orderEntry type="library" exported="" name="jsr305-3.0.0" level="project" />
<orderEntry type="library" exported="" name="stetho-1.2.0" level="project" />
<orderEntry type="library" exported="" name="jackson-core-2.2.3" level="project" />
<orderEntry type="library" exported="" name="fbcore-0.8.1" level="project" />
<orderEntry type="library" exported="" name="commons-cli-1.2" level="project" />
......
......@@ -469,12 +469,15 @@ public class GLCanvas extends GLSurfaceView
}
Map<String, Integer> uniformTypes = shader.getUniformTypes();
List<String> uniformNames = shader.getUniformNames();
Map<String, Integer> uniformSizes = shader.getUniformSizes();
int units = 0;
ReadableMapKeySetIterator iterator = data.uniforms.keySetIterator();
while (iterator.hasNextKey()) {
String uniformName = iterator.nextKey();
int type = uniformTypes.get(uniformName);
int size = uniformSizes.get(uniformName);
ReadableMap dataUniforms = data.uniforms;
......@@ -530,6 +533,7 @@ public class GLCanvas extends GLSurfaceView
}
}
else {
if (size == 1) {
switch (type) {
case GL_INT:
uniformsInteger.put(uniformName, dataUniforms.getInt(uniformName));
......@@ -580,7 +584,69 @@ public class GLCanvas extends GLSurfaceView
"uniform '"+uniformName+
"': type not supported: "+type);
}
}
else {
ReadableArray array = dataUniforms.getArray(uniformName);
if (size != array.size()) {
shader.runtimeException(
"uniform '"+uniformName+
"': Invalid array size: "+array.size()+
". Expected: "+size);
}
for (int i=0; i<size; i++) {
String name = uniformName+"["+i+"]";
switch (type) {
case GL_INT:
uniformsInteger.put(name, array.getInt(i));
break;
case GL_BOOL:
uniformsInteger.put(name, array.getBoolean(i) ? 1 : 0);
break;
case GL_FLOAT:
uniformsFloat.put(name, (float) array.getDouble(i));
break;
case GL_FLOAT_VEC2:
case GL_FLOAT_VEC3:
case GL_FLOAT_VEC4:
case GL_FLOAT_MAT2:
case GL_FLOAT_MAT3:
case GL_FLOAT_MAT4:
ReadableArray arr = array.getArray(i);
if (arraySizeForType(type) != arr.size()) {
shader.runtimeException(
"uniform '"+name+
"': Invalid array size: "+arr.size()+
". Expected: "+arraySizeForType(type));
}
uniformsFloatBuffer.put(name, parseAsFloatArray(arr));
break;
case GL_INT_VEC2:
case GL_INT_VEC3:
case GL_INT_VEC4:
case GL_BOOL_VEC2:
case GL_BOOL_VEC3:
case GL_BOOL_VEC4:
ReadableArray arr2 = array.getArray(i);
if (arraySizeForType(type) != arr2.size()) {
shader.runtimeException(
"uniform '"+name+
"': Invalid array size: "+arr2.size()+
". Expected: "+arraySizeForType(type));
}
uniformsIntBuffer.put(name, parseAsIntArray(arr2));
break;
default:
shader.runtimeException(
"uniform '"+name+
"': type not supported: "+type);
}
}
}
}
}
......@@ -590,12 +656,26 @@ public class GLCanvas extends GLSurfaceView
shader.runtimeException("Maximum number of texture reach. got " + units + " >= max " + maxTextureUnits);
}
for (String uniformName: uniformTypes.keySet()) {
for (String uniformName: uniformNames) {
int size = uniformSizes.get(uniformName);
if (size == 1) {
if (!uniformsFloat.containsKey(uniformName) &&
!uniformsInteger.containsKey(uniformName) &&
!uniformsFloatBuffer.containsKey(uniformName) &&
!uniformsIntBuffer.containsKey(uniformName)) {
shader.runtimeException("All defined uniforms must be provided. Missing '"+uniformName+"'");
shader.runtimeException("All defined uniforms must be provided. Missing '" + uniformName + "'");
}
}
else {
for (int i=0; i<size; i++) {
String name = uniformName+"["+i+"]";
if (!uniformsFloat.containsKey(name) &&
!uniformsInteger.containsKey(name) &&
!uniformsFloatBuffer.containsKey(name) &&
!uniformsIntBuffer.containsKey(name)) {
shader.runtimeException("All defined uniforms must be provided. Missing '" + name + "'");
}
}
}
}
......
......@@ -7,7 +7,9 @@ import java.nio.ByteBuffer;
import java.nio.ByteOrder;
import java.nio.FloatBuffer;
import java.nio.IntBuffer;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
public class GLShader {
......@@ -16,10 +18,12 @@ public class GLShader {
private final String vert;
private final String frag;
private Map<String, Integer> uniformTypes;
private List<String> uniformNames;
private int program; // Program of the shader
private int buffer[]; // the buffer currently contains 2 static triangles covering the surface
private int pointerLoc; // The "pointer" attribute is used to iterate over vertex
private Map<String, Integer> uniformLocations; // The uniform locations cache
private Map<String, Integer> uniformSizes; // The size of the uniform variable
private Integer id;
private RNGLContext rnglContext;
......@@ -76,6 +80,7 @@ public class GLShader {
glUniform1f(uniformLocations.get(name), f);
}
public void setUniform (String name, FloatBuffer buf, int type) {
System.out.println("setUniform "+name);
switch (type) {
case GL_FLOAT_VEC2:
glUniform2fv(uniformLocations.get(name), 1, buf);
......@@ -125,7 +130,10 @@ public class GLShader {
public Map<String, Integer> getUniformTypes() {
return uniformTypes;
}
public Map<String, Integer> getUniformSizes() {
return uniformSizes;
}
public List<String> getUniformNames() { return uniformNames; }
private int compileShader (String code, int shaderType) {
int shaderHandle = glCreateShader(shaderType);
......@@ -143,19 +151,42 @@ public class GLShader {
private void computeMeta () {
Map<String, Integer> uniforms = new HashMap<>();
Map<String, Integer> locations = new HashMap<>();
Map<String, Integer> sizes = new HashMap<>();
ArrayList<String> uniformNames = new ArrayList<>();
int[] nbUniforms = new int[1];
int[] type = new int[1];
int[] size = new int[1];
int[] typePointer = new int[1];
int[] sizePointer = new int[1];
glGetProgramiv(program, GL_ACTIVE_UNIFORMS, nbUniforms, 0);
for (int i=0; i < nbUniforms[0]; i++) {
String uniformName = glGetActiveUniform(program, i, size, 0, type, 0);
String uniformName = glGetActiveUniform(program, i, sizePointer, 0, typePointer, 0);
int size = sizePointer[0];
int type = typePointer[0];
if (uniformName.contains("[0]")) {
uniformName = uniformName.substring(0, uniformName.length()-3);
}
uniformNames.add(uniformName);
uniforms.put(uniformName, type);
sizes.put(uniformName, size);
if (size == 1) {
int location = glGetUniformLocation(program, uniformName);
uniforms.put(uniformName, type[0]);
locations.put(uniformName, location);
}
else {
for (int j=0; j<size; j++) {
String uniformIndexName = uniformName+ "[" + j + "]";
int location = glGetUniformLocation(program, uniformIndexName);
locations.put(uniformIndexName, location);
uniforms.put(uniformIndexName, type);
sizes.put(uniformIndexName, 1);
}
}
}
this.uniformTypes = uniforms;
this.uniformLocations = locations;
this.uniformSizes = sizes;
this.uniformNames = uniformNames;
}
private void makeProgram () throws GLShaderCompilationFailed {
......
This diff is collapsed.
......@@ -5,7 +5,7 @@ buildscript {
jcenter()
}
dependencies {
classpath 'com.android.tools.build:gradle:1.3.1'
classpath 'com.android.tools.build:gradle:2.1.2'
// NOTE: Do not place your application dependencies here; they belong
// in the individual module build.gradle files
......
#Mon Jun 13 21:59:23 CEST 2016
distributionBase=GRADLE_USER_HOME
distributionPath=wrapper/dists
zipStoreBase=GRADLE_USER_HOME
zipStorePath=wrapper/dists
distributionUrl=https\://services.gradle.org/distributions/gradle-2.4-all.zip
distributionUrl=https\://services.gradle.org/distributions/gradle-2.10-all.zip
import React, {Component} from "react";
import {View, Animated} from "react-native";
import {Surface} from "gl-react-native";
import GL from "gl-react";
const stateForTime = t => ({
colors: [
[ Math.cos(0.002*t), Math.sin(0.002*t), 0.2, 1 ],
[ Math.sin(0.002*t), -Math.cos(0.002*t), 0.1, 1 ],
[ 0.3, Math.sin(3+0.002*t), Math.cos(1+0.003*t), 1 ]
],
particles: [
[ 0.3, 0.3 ],
[ 0.7, 0.5 ],
[ 0.4, 0.9 ]
]
});
export default class AnimatedExample extends Component {
state = stateForTime(0);
componentWillMount () {
const begin = Date.now();
this.interval = setInterval(() => this.setState(
stateForTime(Date.now() - begin)
));
}
componentWillUnmount () {
clearInterval(this.interval);
}
render () {
const { colors, particles } = this.state;
return <View style={{ paddingTop: 60, alignItems: "center" }}>
<Surface width={300} height={300}>
<GL.Node
uniforms={{
colors,
particles,
}}
shader={{// inline example
frag: `
precision highp float;
varying vec2 uv;
uniform vec4 colors[3];
uniform vec2 particles[3]; // N.B. don't abuse these technique. it's not meant to be used with lot of objects.
void main () {
vec4 sum = vec4(0.0);
for (int i=0; i<3; i++) {
vec4 c = colors[i];
vec2 p = particles[i];
float d = c.a * smoothstep(0.6, 0.2, distance(p, uv));
sum += d * vec4(c.a * c.rgb, c.a);
}
if (sum.a > 1.0) {
sum.rgb /= sum.a;
sum.a = 1.0;
}
gl_FragColor = vec4(sum.a * sum.rgb, 1.0);
}
`
}}
/>
</Surface>
</View>;
}
}
......@@ -6,22 +6,15 @@ import AdvancedEffects from "./AdvancedEffects";
import Hearts from "./Hearts";
import Tests from "./Tests";
import Animated from "./Animated";
import Particles from "./Particles";
const screens = { Simple, AdvancedEffects, Hearts, Tests, Animated };
const screens = { Simple, AdvancedEffects, Hearts, Tests, Animated, Particles };
const homeRoute = {
id: "home",
title: "gl-react Showcase"
};
const routes = [
{ id: "Simple" },
{ id: "AdvancedEffects" },
{ id: "Hearts" },
{ id: "Tests" },
{ id: "Animated" },
];
const styles = StyleSheet.create({
root: {
backgroundColor: "#333",
......@@ -62,9 +55,9 @@ class Home extends Component {
render () {
const { openScreen } = this.props;
return <View style={styles.home}>
{routes.map(route =>
<TouchableOpacity style={styles.homeLink} key={route.id} onPress={() => openScreen(route)}>
<Text style={styles.homeText}>{route.id}</Text>
{Object.keys(screens).map(id =>
<TouchableOpacity style={styles.homeLink} key={id} onPress={() => openScreen({ id })}>
<Text style={styles.homeText}>{id}</Text>
</TouchableOpacity>)}
</View>;
}
......
......@@ -283,7 +283,7 @@ RCT_NOT_IMPLEMENTED(-init)
RCTLogError(@"Maximum number of texture reach. got %i >= max %i", units, maxTextureUnits);
}
for (NSString *uniformName in shader.uniformTypes) {
for (NSString *uniformName in shader.uniformNames) {
if (uniforms[uniformName] == nil) {
RCTLogError(@"All defined uniforms must be provided. Missing '%@'", uniformName);
}
......
......@@ -14,6 +14,7 @@ NS_ENUM(NSInteger) {
@property EAGLContext *context;
@property NSString *vert;
@property NSString *frag;
@property NSArray *uniformNames;
@property NSDictionary *uniformTypes;
/**
......
......@@ -40,8 +40,10 @@ GLuint compileShader (NSString* shaderName, NSString* shaderString, GLenum shade
GLuint program; // Program of the shader
GLuint buffer; // the buffer currently contains 2 static triangles covering the surface
GLint pointerLoc; // The "pointer" attribute is used to iterate over vertex
NSDictionary *_uniformTypes; // The types of the GLSL uniforms (N.B: array are not supported)
NSDictionary *_uniformTypes; // The types of the GLSL uniforms
NSDictionary *_uniformSizes; // The size of the uniform variable
NSDictionary *_uniformLocations; // The uniform locations cache
NSArray *__uniformNames; // The uniforms names
NSError *_error;
}
......@@ -95,12 +97,27 @@ GLuint compileShader (NSString* shaderName, NSString* shaderString, GLenum shade
- (void) setUniform: (NSString *)name withValue:(id)value
{
GLint size = [_uniformSizes[name] intValue];
GLenum type = [_uniformTypes[name] intValue];
if (size != 1) {
NSArray *v = [RCTConvert NSArray:value];
if (!v || [v count]!=size) {
RCTLogError(@"Shader '%@': uniform '%@' should be an array of %i elements", _name, name, size);
return;
}
for (int i=0; i<size; i++) {
NSString *indexName = [NSString stringWithFormat:@"%@[%i]", name, i];
id indexValue = v[i];
[self setUniform:indexName withValue:indexValue];
}
return;
}
if ([_uniformLocations objectForKey:name] == nil) {
RCTLogError(@"Shader '%@': uniform '%@' does not exist", _name, name);
return;
}
GLint location = [_uniformLocations[name] intValue];
GLenum type = [_uniformTypes[name] intValue];
switch (type)
{
......@@ -318,8 +335,10 @@ GLuint compileShader (NSString* shaderName, NSString* shaderString, GLenum shade
- (void) computeMeta
{
NSMutableDictionary *uniforms = @{}.mutableCopy;
NSMutableArray *uniformNames = [[NSMutableArray alloc] init];
NSMutableDictionary *uniformTypes = @{}.mutableCopy;
NSMutableDictionary *locations = @{}.mutableCopy;
NSMutableDictionary *sizes = @{}.mutableCopy;
int nbUniforms;
GLchar name[256];
GLenum type;
......@@ -328,14 +347,33 @@ GLuint compileShader (NSString* shaderName, NSString* shaderString, GLenum shade
glGetProgramiv(program, GL_ACTIVE_UNIFORMS, &nbUniforms);
for (int i=0; i<nbUniforms; i++) {
glGetActiveUniform(program, i, sizeof(name), &length, &size, &type, name);
GLint location = glGetUniformLocation(program, name);
NSString *uniformName = [NSString stringWithUTF8String:name];
uniforms[uniformName] = [NSNumber numberWithInt:type];
locations[uniformName] = [NSNumber numberWithInt:location];
if ([uniformName containsString:@"[0]"]) {
uniformName = [uniformName substringToIndex:[uniformName length]-3];
}
uniformTypes[uniformName] = [NSNumber numberWithInt:type];
sizes[uniformName] = [NSNumber numberWithInt:size];
[uniformNames addObject:uniformName];
if (size == 1) {
GLint location = glGetUniformLocation(program, name);
locations[uniformName] = [NSNumber numberWithInt:location];
}
_uniformTypes = uniforms;
else {
for (int j=0; j<size; j++) {
NSString *uniformIndexName = [NSString stringWithFormat:@"%@[%i]", uniformName, j];
GLint location = glGetUniformLocation(program, [uniformIndexName UTF8String]);
locations[uniformIndexName] = [NSNumber numberWithInt:location];
uniformTypes[uniformIndexName] = [NSNumber numberWithInt:type];
sizes[uniformIndexName] = [NSNumber numberWithInt:1];
}
}
}
_uniformTypes = uniformTypes;
_uniformLocations = locations;
_uniformSizes = sizes;
_uniformNames = uniformNames;
}
- (bool) ensureCompiles: (NSError **)error
......
......@@ -20,7 +20,7 @@
"license": "MIT",
"peerDependencies": {
"react-native": "*",
"gl-react": "^2.2.0"
"gl-react": "^2.2.3"
},
"dependencies": {
"invariant": "2.2.0",
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment