Skip to content

Commit 0c051ec

Browse files
authored
Merge pull request #125 from vidartf/shaders
Workable ShaderMaterial
2 parents 966825c + 716a63a commit 0c051ec

12 files changed

+345
-46
lines changed

.gitignore

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -16,6 +16,7 @@ pythreejs/static/
1616
# Autogen files
1717
*_autogen.py
1818
*.autogen.js
19+
*.autogen.json
1920
js/src/**/index.js
2021
pythreejs/**/__init__.py
2122

README.md

Lines changed: 0 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -6,10 +6,6 @@ A Python / ThreeJS bridge utilizing the Jupyter widget infrastructure.
66

77
## Getting Started
88

9-
### Try it online with [Binder](http://mybinder.org/)
10-
11-
[![Binder](http://mybinder.org/badge.svg)](http://mybinder.org:/repo/jovyan/pythreejs/notebooks/examples)
12-
139
### Installation
1410

1511
Using pip:

environment.yml

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,5 @@
11
name: pythreejs
22
channels:
3-
- nodefaults
43
- conda-forge
54
dependencies:
65
- pythreejs

examples/Shaders.ipynb

Lines changed: 155 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,155 @@
1+
{
2+
"cells": [
3+
{
4+
"cell_type": "markdown",
5+
"metadata": {},
6+
"source": [
7+
"This notebook gives a simple example of how to use the ShaderMaterial to write custom shaders from the Python side. For further information about the shaders, consult the three.js docs."
8+
]
9+
},
10+
{
11+
"cell_type": "code",
12+
"execution_count": null,
13+
"metadata": {},
14+
"outputs": [],
15+
"source": [
16+
"from pythreejs import *\n",
17+
"import ipywidgets\n",
18+
"from IPython.display import display"
19+
]
20+
},
21+
{
22+
"cell_type": "code",
23+
"execution_count": null,
24+
"metadata": {},
25+
"outputs": [],
26+
"source": [
27+
"ShaderMaterial?"
28+
]
29+
},
30+
{
31+
"cell_type": "code",
32+
"execution_count": null,
33+
"metadata": {},
34+
"outputs": [],
35+
"source": [
36+
"vertex_shader = \"\"\"\n",
37+
"uniform float time;\n",
38+
"uniform vec2 resolution;\n",
39+
"\n",
40+
"void main() {\n",
41+
" vec3 pos = vec3(position.x + time * resolution.x, position.y + time * resolution.y, position.z);\n",
42+
" gl_Position = projectionMatrix * modelViewMatrix * vec4( pos, 1.0 );\n",
43+
"}\n",
44+
"\"\"\""
45+
]
46+
},
47+
{
48+
"cell_type": "code",
49+
"execution_count": null,
50+
"metadata": {},
51+
"outputs": [],
52+
"source": [
53+
"fragment_shader = \"\"\"\n",
54+
"void main() {\n",
55+
" #ifdef OVERRIDE_COLOR\n",
56+
" gl_FragColor = vec4(0, 0.5, 0, 1.0);\n",
57+
" #else\n",
58+
" gl_FragColor = vec4(0.5, 0, 0, 1.0);\n",
59+
" #endif\n",
60+
"}\n",
61+
"\"\"\""
62+
]
63+
},
64+
{
65+
"cell_type": "code",
66+
"execution_count": null,
67+
"metadata": {},
68+
"outputs": [],
69+
"source": [
70+
"material = ShaderMaterial(\n",
71+
" uniforms=dict(\n",
72+
" time=dict(value=0.0),\n",
73+
" resolution=dict(value=(1, 1)),\n",
74+
" **UniformsLib['lights']\n",
75+
" ),\n",
76+
" defines=dict(\n",
77+
" OVERRIDE_COLOR=1,\n",
78+
" ),\n",
79+
" vertexShader=vertex_shader,\n",
80+
" fragmentShader=fragment_shader,\n",
81+
" lights=True,\n",
82+
")"
83+
]
84+
},
85+
{
86+
"cell_type": "code",
87+
"execution_count": null,
88+
"metadata": {},
89+
"outputs": [],
90+
"source": [
91+
"material"
92+
]
93+
},
94+
{
95+
"cell_type": "code",
96+
"execution_count": null,
97+
"metadata": {},
98+
"outputs": [],
99+
"source": [
100+
"material.defines = dict()\n",
101+
"material.needsUpdate = True"
102+
]
103+
},
104+
{
105+
"cell_type": "code",
106+
"execution_count": null,
107+
"metadata": {},
108+
"outputs": [],
109+
"source": [
110+
"def update_time(time):\n",
111+
" uniforms = dict(**material.uniforms)\n",
112+
" uniforms.update(time=dict(value=time))\n",
113+
" material.uniforms = uniforms\n",
114+
" material.needsUpdate = True"
115+
]
116+
},
117+
{
118+
"cell_type": "code",
119+
"execution_count": null,
120+
"metadata": {},
121+
"outputs": [],
122+
"source": [
123+
"update_time(-15)"
124+
]
125+
},
126+
{
127+
"cell_type": "code",
128+
"execution_count": null,
129+
"metadata": {},
130+
"outputs": [],
131+
"source": []
132+
}
133+
],
134+
"metadata": {
135+
"kernelspec": {
136+
"display_name": "Python 3",
137+
"language": "python",
138+
"name": "python3"
139+
},
140+
"language_info": {
141+
"codemirror_mode": {
142+
"name": "ipython",
143+
"version": 3
144+
},
145+
"file_extension": ".py",
146+
"mimetype": "text/x-python",
147+
"name": "python",
148+
"nbconvert_exporter": "python",
149+
"pygments_lexer": "ipython3",
150+
"version": "3.5.4"
151+
}
152+
},
153+
"nbformat": 4,
154+
"nbformat_minor": 2
155+
}

js/package.json

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -12,7 +12,9 @@
1212
"scripts": {
1313
"clean": "rimraf dist && rimraf ../pythreejs/static && node ./scripts/clean-generated-files.js",
1414
"autogen-enums": "node ./scripts/generate-enums.js",
15-
"autogen": "node ./scripts/generate-wrappers.js",
15+
"autogen-shaders": "node ./scripts/generate-shader-utils.js",
16+
"autogen-wrappers": "node ./scripts/generate-wrappers.js",
17+
"autogen": "npm run autogen-shaders && npm run autogen-wrappers",
1618
"build": "webpack && node ./scripts/copy-three.js",
1719
"prepublish": "npm run autogen && npm run build"
1820
},

js/scripts/clean-generated-files.js

Lines changed: 25 additions & 23 deletions
Original file line numberDiff line numberDiff line change
@@ -10,16 +10,16 @@ var scriptDir = __dirname;
1010
var baseDir = path.resolve(scriptDir, '..');
1111

1212
// Execute a function for each match to a glob query
13-
//
13+
//
1414
// Parameters:
1515
// globPattern: String glob pattern for node-glob
1616
// mapFn: Function function(pathRelativeToCwd), should return a promise or list of promises
1717
// globOptions: Object of options passed directly to node-glob
1818
//
1919
// Returns: Promise that resolves with array of results from mapFn applies to all glob matches
20-
function mapPromiseFnOverGlob(globPattern, mapFn, globOptions) {
20+
function mapPromiseFnOverGlob(globPattern, mapFn, globOptions) {
2121
return new Promise(function(resolve, reject) {
22-
22+
2323
var promises = [];
2424

2525
// trailing slash will match only directories
@@ -31,7 +31,7 @@ function mapPromiseFnOverGlob(globPattern, mapFn, globOptions) {
3131
} else if (result instanceof Promise) {
3232
promises.push(result);
3333
} else {
34-
promises.push(Promise.resolve(result));
34+
promises.push(Promise.resolve(result));
3535
}
3636
})
3737
.on('end', function() {
@@ -49,37 +49,39 @@ function mapPromiseFnOverGlob(globPattern, mapFn, globOptions) {
4949
}
5050

5151
function rmFileGlobAsync(globPattern) {
52-
return mapPromiseFnOverGlob(globPattern, function(filePath) {
53-
console.log(filePath);
54-
var absPath = path.resolve(baseDir, filePath);
55-
return fse.removeAsync(absPath);
56-
}, {
57-
cwd: baseDir,
52+
return mapPromiseFnOverGlob(globPattern, function(filePath) {
53+
console.log(filePath);
54+
var absPath = path.resolve(baseDir, filePath);
55+
return fse.removeAsync(absPath);
56+
}, {
57+
cwd: baseDir,
5858
nodir: true,
5959
ignore: [
60-
'./node_modules/**'
60+
'./node_modules/**'
6161
]
6262
});
6363
}
6464

6565
function cleanGeneratedFilesAsync() {
66-
// trailing slash will match only directories
67-
var jsPromise = rmFileGlobAsync('./**/*.autogen.js');
68-
var jsIndexPromise = rmFileGlobAsync('./**/index.js');
66+
// trailing slash will match only directories
67+
var jsPromise = rmFileGlobAsync('./**/*.autogen.js');
68+
var jsonPromise = rmFileGlobAsync('./**/*.autogen.json');
69+
var jsIndexPromise = rmFileGlobAsync('./**/index.js');
6970

70-
var pyPromise = rmFileGlobAsync('../pythreejs/**/*_autogen.py');
71-
var pyIndexPromise = rmFileGlobAsync('../pythreejs/**/__init__.py');
71+
var pyPromise = rmFileGlobAsync('../pythreejs/**/*_autogen.py');
72+
var pyIndexPromise = rmFileGlobAsync('../pythreejs/**/__init__.py');
7273

73-
return Promise.all([
74-
jsPromise,
75-
jsIndexPromise,
76-
pyPromise,
77-
pyIndexPromise,
78-
]);
74+
return Promise.all([
75+
jsPromise,
76+
jsonPromise,
77+
jsIndexPromise,
78+
pyPromise,
79+
pyIndexPromise,
80+
]);
7981
}
8082

8183
if (require.main === module) {
8284
cleanGeneratedFilesAsync().then(function() {
8385
console.log('DONE');
8486
});
85-
}
87+
}

0 commit comments

Comments
 (0)