diff --git a/android/RNGL.iml b/android/RNGL.iml
index 56c669ccb2d1b374b79fc689cfa63bb347447ba0..ae08619d47a1df69e5929443be2748c840de57c2 100644
--- a/android/RNGL.iml
+++ b/android/RNGL.iml
@@ -12,10 +12,7 @@
-
-
- generateDebugAndroidTestSources
generateDebugSources
@@ -29,7 +26,7 @@
-
+
@@ -51,6 +48,15 @@
+
+
+
+
+
+
+
+
+
@@ -58,6 +64,15 @@
+
+
+
+
+
+
+
+
+
@@ -65,17 +80,31 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
@@ -86,8 +115,8 @@
-
+
diff --git a/android/src/main/java/com/projectseptember/RNGL/GLCanvas.java b/android/src/main/java/com/projectseptember/RNGL/GLCanvas.java
index 7016a1a2a0cc281659c6102f4e154a9024bdd2cc..4b12b770e5b576c0ade9145f41e095e0732ed4bc 100644
--- a/android/src/main/java/com/projectseptember/RNGL/GLCanvas.java
+++ b/android/src/main/java/com/projectseptember/RNGL/GLCanvas.java
@@ -469,12 +469,15 @@ public class GLCanvas extends GLSurfaceView
}
Map uniformTypes = shader.getUniformTypes();
+ List uniformNames = shader.getUniformNames();
+ Map 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,57 +533,120 @@ public class GLCanvas extends GLSurfaceView
}
}
else {
- switch (type) {
- case GL_INT:
- uniformsInteger.put(uniformName, dataUniforms.getInt(uniformName));
- break;
-
- case GL_BOOL:
- uniformsInteger.put(uniformName, dataUniforms.getBoolean(uniformName) ? 1 : 0);
- break;
-
- case GL_FLOAT:
- uniformsFloat.put(uniformName, (float) dataUniforms.getDouble(uniformName));
- 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 = dataUniforms.getArray(uniformName);
- if (arraySizeForType(type) != arr.size()) {
+ if (size == 1) {
+ switch (type) {
+ case GL_INT:
+ uniformsInteger.put(uniformName, dataUniforms.getInt(uniformName));
+ break;
+
+ case GL_BOOL:
+ uniformsInteger.put(uniformName, dataUniforms.getBoolean(uniformName) ? 1 : 0);
+ break;
+
+ case GL_FLOAT:
+ uniformsFloat.put(uniformName, (float) dataUniforms.getDouble(uniformName));
+ 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 = dataUniforms.getArray(uniformName);
+ if (arraySizeForType(type) != arr.size()) {
+ shader.runtimeException(
+ "uniform '"+uniformName+
+ "': Invalid array size: "+arr.size()+
+ ". Expected: "+arraySizeForType(type));
+ }
+ uniformsFloatBuffer.put(uniformName, 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 = dataUniforms.getArray(uniformName);
+ if (arraySizeForType(type) != arr2.size()) {
+ shader.runtimeException(
+ "uniform '"+uniformName+
+ "': Invalid array size: "+arr2.size()+
+ ". Expected: "+arraySizeForType(type));
+ }
+ uniformsIntBuffer.put(uniformName, parseAsIntArray(arr2));
+ break;
+
+ default:
shader.runtimeException(
"uniform '"+uniformName+
- "': Invalid array size: "+arr.size()+
- ". Expected: "+arraySizeForType(type));
- }
- uniformsFloatBuffer.put(uniformName, 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 = dataUniforms.getArray(uniformName);
- if (arraySizeForType(type) != arr2.size()) {
- shader.runtimeException(
- "uniform '"+uniformName+
- "': Invalid array size: "+arr2.size()+
- ". Expected: "+arraySizeForType(type));
- }
- uniformsIntBuffer.put(uniformName, parseAsIntArray(arr2));
- break;
-
- default:
+ "': type not supported: "+type);
+ }
+ }
+ else {
+ ReadableArray array = dataUniforms.getArray(uniformName);
+ if (size != array.size()) {
shader.runtimeException(
"uniform '"+uniformName+
- "': type not supported: "+type);
- }
+ "': Invalid array size: "+array.size()+
+ ". Expected: "+size);
+ }
+ for (int i=0; i= max " + maxTextureUnits);
}
- for (String uniformName: uniformTypes.keySet()) {
- if (!uniformsFloat.containsKey(uniformName) &&
- !uniformsInteger.containsKey(uniformName) &&
- !uniformsFloatBuffer.containsKey(uniformName) &&
- !uniformsIntBuffer.containsKey(uniformName)) {
- shader.runtimeException("All defined uniforms must be provided. Missing '"+uniformName+"'");
+ 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 + "'");
+ }
+ }
+ else {
+ for (int i=0; i uniformTypes;
+ private List 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 uniformLocations; // The uniform locations cache
+ private Map 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 getUniformTypes() {
return uniformTypes;
}
-
+ public Map getUniformSizes() {
+ return uniformSizes;
+ }
+ public List 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 uniforms = new HashMap<>();
Map locations = new HashMap<>();
+ Map sizes = new HashMap<>();
+ ArrayList 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);
- int location = glGetUniformLocation(program, uniformName);
- uniforms.put(uniformName, type[0]);
- locations.put(uniformName, location);
+ 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);
+ locations.put(uniformName, location);
+ }
+ else {
+ for (int j=0; j
-
-
- generateDebugAndroidTestSources
generateDebugSources
@@ -28,7 +25,7 @@
-
+
@@ -50,6 +47,15 @@
+
+
+
+
+
+
+
+
+
@@ -57,6 +63,15 @@
+
+
+
+
+
+
+
+
+
@@ -64,54 +79,68 @@
+
+
+
+
-
-
-
-
-
-
-
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
-
+
-
-
-
-
+
+
+
-
-
+
+
-
+
+
-
-
+
-
-
-
+
+
-
+
+
diff --git a/example/android/build.gradle b/example/android/build.gradle
index 403a007564d9480e97c4cb7a54a5bdf64491fca6..adc2df71dfb5ce0214854352f81e0dd147f6d399 100644
--- a/example/android/build.gradle
+++ b/example/android/build.gradle
@@ -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
diff --git a/example/android/gradle/wrapper/gradle-wrapper.properties b/example/android/gradle/wrapper/gradle-wrapper.properties
index b9fbfaba0ead2162e30db62f51e95df8a670d4a6..7ce224952c8c9bd626357bdee64dda2b12713912 100644
--- a/example/android/gradle/wrapper/gradle-wrapper.properties
+++ b/example/android/gradle/wrapper/gradle-wrapper.properties
@@ -1,5 +1,6 @@
+#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
diff --git a/example/src/Particles/index.js b/example/src/Particles/index.js
new file mode 100644
index 0000000000000000000000000000000000000000..ff64f478ac8b179a2f53c1d4d68160df8e3e106b
--- /dev/null
+++ b/example/src/Particles/index.js
@@ -0,0 +1,65 @@
+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
+
+ 1.0) {
+ sum.rgb /= sum.a;
+ sum.a = 1.0;
+ }
+ gl_FragColor = vec4(sum.a * sum.rgb, 1.0);
+}
+ `
+ }}
+ />
+
+ ;
+ }
+}
diff --git a/example/src/index.js b/example/src/index.js
index 6395a1d01e14da4dde6e62fb66d6aaf1c754e6f8..93806439f2dbda4a0c28f155bbc7fa42b9b2c013 100644
--- a/example/src/index.js
+++ b/example/src/index.js
@@ -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
- {routes.map(route =>
- openScreen(route)}>
- {route.id}
+ {Object.keys(screens).map(id =>
+ openScreen({ id })}>
+ {id}
)}
;
}
diff --git a/ios/GLCanvas.m b/ios/GLCanvas.m
index affe1a28891a59cc93c61068d80129a693fc21f2..3578b98c0dc3c7854d3dc0e0c2d23c6af59ca372 100644
--- a/ios/GLCanvas.m
+++ b/ios/GLCanvas.m
@@ -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);
}
diff --git a/ios/GLShader.h b/ios/GLShader.h
index 90c20142ec6eca7c6802449340d99a94a797e908..4166ae28f5eabbd3f4d6385fe102c8a4f5a40340 100644
--- a/ios/GLShader.h
+++ b/ios/GLShader.h
@@ -14,6 +14,7 @@ NS_ENUM(NSInteger) {
@property EAGLContext *context;
@property NSString *vert;
@property NSString *frag;
+@property NSArray *uniformNames;
@property NSDictionary *uniformTypes;
/**
diff --git a/ios/GLShader.m b/ios/GLShader.m
index 5780018622d3cacad7ef85663008f046a7b6585a..d5d951b189a3d571638ab11422bdb56cdf7926ee 100644
--- a/ios/GLShader.m
+++ b/ios/GLShader.m
@@ -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,13 +97,28 @@ 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