Skip to content

Commit 94f30fe

Browse files
committed
blending started
1 parent 6e7bb68 commit 94f30fe

File tree

10 files changed

+193
-0
lines changed

10 files changed

+193
-0
lines changed

exercises.json

+1
Original file line numberDiff line numberDiff line change
@@ -23,5 +23,6 @@
2323
"» SECOND CHALLENGE: A SPINNING CUBE": "@exercise/challenge-1",
2424
"» ADVANCED DRAWING: LINE WIDTH": "@exercise/drawing-line-width",
2525
"» ADVANCED DRAWING: COLOR MASK": "@exercise/drawing-color-mask",
26+
"» BLENDING: BASICS": "@exercise/blend-basics",
2627
"» STENCIL: STENCIL SHADOWS": "@exercise/stencil-shadows"
2728
}

exercises/blend-basics/README.md

+45
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,45 @@
1+
# Exercise
2+
3+
# Blending
4+
5+
In WebGL, blending combines the contents of the currently rendered fragment with the color value stored in the drawing buffer to compute a new color value.
6+
7+
By convention, the fragment being drawn is called the *source* and the fragment in the drawing buffer is called the *destination*.
8+
9+
By default, the new fragment color is just the source color, however if we turn on blending:
10+
11+
```javascript
12+
gl.enable(gl.BLEND)
13+
```
14+
15+
Then the color of the resulting fragment is computed as a weighted combination of the source and destination fragments. To specify these weights, we can use the following command:
16+
17+
#### `gl.blendFuncSeparate(sourceRGB, sourceAlpha, destRGB, destAlpha)`
18+
19+
Each of the parameter `sourceRGB`, `sourceAlpha`, `destRGB`, `destAlpha` describes the weight which is applied to either the source or destination fragment. The possible values for these weights are as follows:
20+
21+
* `gl.ZERO`: (0,0,0,0)
22+
* `gl.ONE`: (1,1,1,1)
23+
* `gl.SRC_COLOR`: (Rs, Gs, Bs, As)
24+
* `gl.ONE_MINUS_SRC_COLOR`: (1,1,1,1)−(Rs,Gs,Bs,As)
25+
* `gl.DST_COLOR`: (Rd, Gd, Bd, Ad)
26+
* `gl.ONE_MINUS_DST_COLOR`: (1,1,1,1)−(Rd,Gd,Bd,Ad)
27+
* `gl.SRC_ALPHA`: (As, As, As, As)
28+
* `gl.ONE_MINUS_SRC_ALPHA`: (1,1,1,1)−(As,As,As,As)
29+
* `gl.DST_ALPHA`: (Ad, Ad, Ad, Ad)
30+
* `gl.ONE_MINUS_DST_ALPHA`: (1,1,1,1)−(Ad,Ad,Ad,Ad)
31+
32+
By convention, (Rs, Gs, Bs, As) are the components of the source color and (Rd, Gd, Bd, Ad) are the components of the destination color.
33+
34+
There are also `gl.CONSTANT_COLOR, gl.ONE_MINUS_CONSTANT_COLOR, gl.CONSTANT_ALPHA, gl.ONE_MINUS_CONSTANT_ALPHA` and `gl.SRC_ALPHA_SATURATE`, but don't worry about them for now.
35+
36+
In addition to the above blend functions, you can also change how the
37+
38+
#### `gl.blendEquationSeparate(modeRGB, modeAlpha)`
39+
40+
`modeRGB` and `modeAlpha` control the two different ways of
41+
42+
* `gl.FUNC_ADD`
43+
* `gl.FUNC_SUBTRACT`
44+
* `gl.FUNC_REVERSE_SUBTRACT`
45+

exercises/blend-basics/index.html

+12
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,12 @@
1+
<!doctype html>
2+
<html lang="en">
3+
<head>
4+
<meta charset="UTF-8">
5+
<title>Loading...</title>
6+
<!-- from @workshop/menu/style.css -->
7+
<link rel="stylesheet" href="/style.css">
8+
</head>
9+
<body>
10+
<script charset="utf-8" src="index.js"></script>
11+
</body>
12+
</html>

exercises/blend-basics/index.js

+38
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,38 @@
1+
var Exercise = require('@workshop/exercise')
2+
var compare = require('@workshop/compare')
3+
var fresh = require('fresh-require')
4+
var fit = require('canvas-fit')
5+
var path = require('path')
6+
var fs = require('fs')
7+
8+
// Things for plugging into
9+
var canvas = document.body.appendChild(document.createElement('canvas'))
10+
var readme = fs.readFileSync(__dirname + '/README.md', 'utf8')
11+
var exercise = Exercise(require('./package.json').name)
12+
13+
// Load user submission and the finished solution
14+
var solution = fresh('./solution')
15+
var submission = fresh(process.env.file_index_js)
16+
17+
// Rescale canvas to screen
18+
window.addEventListener('resize'
19+
, fit(canvas)
20+
, false
21+
)
22+
23+
var gl = require('@workshop/common')({
24+
canvas: canvas
25+
, readme: readme
26+
, exercise: exercise
27+
, solution: solution
28+
, submission: submission
29+
, title: 'Basic Drawing'
30+
, file: path.resolve(process.env.project_root, __dirname.slice(1), 'submission', 'index.js')
31+
, test: function(done) {
32+
// >=99% of pixels should be no more than 5 units in difference.
33+
return done(null, compare(
34+
fresh('./solution')
35+
, fresh(process.env.file_index_js)
36+
, 5) >= 0.99)
37+
}
38+
})

exercises/blend-basics/package.json

+6
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,6 @@
1+
{
2+
"name": "@exercise/blend-basics",
3+
"version": "1.0.0",
4+
"main": "server.js",
5+
"dependencies": {}
6+
}

exercises/blend-basics/server.js

+1
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
module.exports = require('@workshop/server-basic')(__dirname)
+20
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,20 @@
1+
var setup = require('../submission/setup')
2+
var drawRect
3+
4+
exports.init = function(gl) {
5+
drawRect = setup(gl)
6+
}
7+
8+
exports.draw = function(gl) {
9+
gl.viewport(0, 0, gl.drawingBufferWidth, gl.drawingBufferHeight)
10+
gl.clearColor(0,0,0,1)
11+
gl.clear(gl.COLOR_BUFFER_BIT)
12+
13+
drawRect([-1,-1], [-0.5,1], [1, 0, 0, 1])
14+
15+
drawRect([-1,-1], [1,-0.5], [0, 0, 1, 1])
16+
17+
drawRect([0.5,-1], [1,1], [0, 1, 0, 1])
18+
19+
drawRect([-1,0.5], [1,1], [1, 1, 1, 1])
20+
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,5 @@
1+
exports.init = function(gl) {
2+
}
3+
4+
exports.draw = function(gl) {
5+
}
+64
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,64 @@
1+
var VERT_SRC = "\
2+
precision mediump float;\
3+
attribute vec2 uvt;\
4+
uniform vec2 uScreenSize, lo, hi;\
5+
void main() {\
6+
vec2 uv = lo + uvt * (hi - lo);\
7+
gl_Position = vec4(uv * vec2(uScreenSize.y / uScreenSize.x, 1) * 0.75, 0, 1);\
8+
}"
9+
10+
var FRAG_SRC = "\
11+
precision mediump float;\
12+
uniform vec4 color;\
13+
void main() {\
14+
gl_FragColor = color;\
15+
}"
16+
17+
function compileShader(gl, type, src) {
18+
var shader = gl.createShader(type)
19+
gl.shaderSource(shader, src)
20+
gl.compileShader(shader)
21+
return shader
22+
}
23+
24+
module.exports = function setup(gl) {
25+
var fragShader = compileShader(gl, gl.FRAGMENT_SHADER, FRAG_SRC)
26+
var vertShader = compileShader(gl, gl.VERTEX_SHADER, VERT_SRC)
27+
28+
var program = gl.createProgram()
29+
gl.attachShader(program, fragShader)
30+
gl.attachShader(program, vertShader)
31+
gl.bindAttribLocation(program, 0, 'uvt')
32+
gl.linkProgram(program)
33+
34+
gl.useProgram(program)
35+
36+
var ulo = gl.getUniformLocation(program, 'lo')
37+
var uhi = gl.getUniformLocation(program, 'hi')
38+
var uScreenSize = gl.getUniformLocation(program, 'uScreenSize')
39+
var ucolor = gl.getUniformLocation(program, 'color')
40+
41+
var vertices = [
42+
0,0,
43+
0,1,
44+
1,0,
45+
1,0,
46+
0,1,
47+
1,1
48+
]
49+
50+
var buffer = gl.createBuffer()
51+
gl.bindBuffer(gl.ARRAY_BUFFER, buffer)
52+
gl.bufferData(gl.ARRAY_BUFFER, new Float32Array(vertices), gl.STATIC_DRAW)
53+
54+
gl.enableVertexAttribArray(0)
55+
gl.vertexAttribPointer(0, 2, gl.FLOAT, false, 0, 0)
56+
57+
return function(lo, hi, color) {
58+
gl.uniform2fv(ulo, lo)
59+
gl.uniform2fv(uhi, hi)
60+
gl.uniform2f(uScreenSize, gl.drawingBufferWidth, gl.drawingBufferHeight)
61+
gl.uniform4fv(ucolor, color)
62+
gl.drawArrays(gl.TRIANGLES, 0, 6)
63+
}
64+
}

package.json

+1
Original file line numberDiff line numberDiff line change
@@ -23,6 +23,7 @@
2323
"@exercise/3d-depth-buffer": "file:exercises/3d-depth-buffer",
2424
"@exercise/3d-front-face": "file:exercises/3d-front-face",
2525
"@exercise/3d-cull-face": "file:exercises/3d-cull-face",
26+
"@exercise/blend-basics": "file:exercises/blend-basics",
2627
"@exercise/buffer-attributes": "file:exercises/buffer-attributes",
2728
"@exercise/buffer-create": "file:exercises/buffer-create",
2829
"@exercise/buffer-draw": "file:exercises/buffer-draw",

0 commit comments

Comments
 (0)