Drawing Multiple Object

This commit is contained in:
monoid 2021-10-02 19:13:52 +09:00
parent 515537ea68
commit ac7b2f400a
7 changed files with 183 additions and 22 deletions

View File

@ -1,9 +1,10 @@
import { Renderer } from './src/renderer'; import { Renderer2D } from './src/renderer';
import React from 'react'; import React from 'react';
import ReactDOM from 'react-dom'; import ReactDOM from 'react-dom';
import { MenuBar } from "./src/menu"; import { MenuBar } from "./src/menu";
import { TriangleRenderer } from './src/triangle_renderer';
function findCanvas(){ function findCanvas(){
const canvas = document.querySelector("canvas"); const canvas = document.querySelector("canvas");
@ -42,19 +43,26 @@ function main(){
setupButton(); setupButton();
const canvas = findCanvas(); const canvas = findCanvas();
const gl = getGLContext(canvas); const gl = getGLContext(canvas);
const renderer = new Renderer(gl); const renderer = new Renderer2D(gl);
renderer.init(); const trenderer = new TriangleRenderer(gl);
renderer.prepare();
trenderer.prepare(gl);
ReactDOM.render(<MenuBar u={renderer.uniforms} ReactDOM.render(<MenuBar u={renderer.uniforms}
onUniformChange={(u)=>{renderer.settingUniform(u); renderer.draw();}} /> onUniformChange={(u)=>{renderer.settingUniform(u); renderer.draw();
trenderer.draw(gl);
}} />
,document.getElementById("drawer")); ,document.getElementById("drawer"));
window.addEventListener("resize",(e)=>{ window.addEventListener("resize",(e)=>{
e.preventDefault(); e.preventDefault();
canvas.width = document.body.clientWidth; canvas.width = document.body.clientWidth;
canvas.height = document.body.clientHeight; canvas.height = document.body.clientHeight;
renderer.draw(); renderer.draw();
trenderer.draw(gl);
}); });
canvas.width = document.body.clientWidth; canvas.width = document.body.clientWidth;
canvas.height = document.body.clientHeight; canvas.height = document.body.clientHeight;
renderer.draw(); renderer.draw();
trenderer.draw(gl);
} }
main(); main();

28
src/app.ts Normal file
View File

@ -0,0 +1,28 @@
import { Renderer2D } from "./renderer";
export class CanvasApp{
readonly gl: WebGL2RenderingContext;
renderer: Renderer2D;
constructor(gl: WebGL2RenderingContext){
this.gl = gl;
this.renderer = new Renderer2D(gl);
}
intialize():boolean{
return true;
}
run(){
const current = new Date();
this.loop();
const delta = (new Date().getMilliseconds()) - current.getMilliseconds();
const delay = (delta < 16) ? (16 - delta) : 1;
setTimeout((()=>{
this.run();
}).bind(this),delay);
}
loop(){
this.gl.clearColor(0,0,0,0);
this.gl.clear(this.gl.COLOR_BUFFER_BIT);
this.renderer.draw();
}
};

54
src/glWrapper.ts Normal file
View File

@ -0,0 +1,54 @@
export class VertexBuffer{
readonly id : WebGLBuffer;
constructor(id : WebGLBuffer){
this.id = id;
}
bind(gl:WebGL2RenderingContext){
gl.bindBuffer(gl.ARRAY_BUFFER,this.id);
}
unbind(gl:WebGL2RenderingContext){
gl.bindBuffer(gl.ARRAY_BUFFER,null);
}
}
/***
* create vertex buffer
* @param gl GLContext
* @param data vertex data to draw
* @example ```
* const buffer = createVertexBuffer(gl,[
* -0.5,0.5,
* 0.5,0.5,
* 0.5,-0.5,
* -0.5,-0.5]);
* ```
*/
export function createVertexBuffer(gl:WebGL2RenderingContext, data:number[]): VertexBuffer{
const id = gl.createBuffer();
gl.bindBuffer(gl.ARRAY_BUFFER,id);
gl.bufferData(gl.ARRAY_BUFFER, new Float32Array(data),gl.STATIC_DRAW);
return new VertexBuffer(id);
}
export class IndexBuffer{
readonly id: WebGLBuffer;
readonly count:number;
constructor(id: WebGLBuffer, count:number){
this.id = id;
this.count = count;
}
bind(gl:WebGL2RenderingContext){
gl.bindBuffer(gl.ELEMENT_ARRAY_BUFFER,this.id);
}
unbind(gl:WebGL2RenderingContext){
gl.bindBuffer(gl.ELEMENT_ARRAY_BUFFER,null);
}
}
export function createIndexBuffer(gl:WebGL2RenderingContext, data:number[]){
const id = gl.createBuffer();
gl.bindBuffer(gl.ELEMENT_ARRAY_BUFFER,id);
gl.bufferData(gl.ELEMENT_ARRAY_BUFFER,new Uint16Array(data),gl.STATIC_DRAW);
return new IndexBuffer(id,data.length);
}

View File

@ -10,10 +10,10 @@ export function MenuBar(prop:{u:UniformSet,onUniformChange:(u:UniformSet)=>void}
}; };
React.useEffect(()=>{ React.useEffect(()=>{
prop.onUniformChange(uniform); prop.onUniformChange(uniform);
}) });
const a = uniform.redcolor*100; const a = uniform.redcolor*100;
return (<div> return (<div>
<Typograpy variant="h4">Uniform</Typograpy> <Typograpy variant="h4">Uniform</Typograpy>
<Slider aria-label="Small" valueLabelDisplay="auto" onChange={onRedChange} value={a}></Slider> <Slider aria-label="Small" valueLabelDisplay="auto" onChange={onRedChange} value={Math.round(a)}></Slider>
</div>); </div>);
} }

4
src/program.ts Normal file
View File

@ -0,0 +1,4 @@
export interface RenderProgram{
draw(gl:WebGL2RenderingContext):void;
};

View File

@ -4,14 +4,18 @@ import {createProgramFromSource, ProgramError, ShaderError} from "./gl_util";
import vert_src from "./vertex.vert"; import vert_src from "./vertex.vert";
import frag_src from "./fragment.frag"; import frag_src from "./fragment.frag";
import { RenderProgram } from "./program";
import * as G from "./glWrapper";
import { getUniformDefaultValue, UniformSet } from "./uniform"; import { getUniformDefaultValue, UniformSet } from "./uniform";
export class Renderer{ export class Renderer2D implements RenderProgram{
gl : WebGL2RenderingContext; gl : WebGL2RenderingContext;
uniforms : UniformSet; uniforms : UniformSet;
program: WebGLProgram; program: WebGLProgram;
positionBuffer: WebGLBuffer;
indexBuffer: WebGLBuffer; vao: WebGLVertexArrayObject;
positionBuffer: G.VertexBuffer;
indexBuffer: G.IndexBuffer;
constructor(gl: WebGL2RenderingContext){ constructor(gl: WebGL2RenderingContext){
this.gl = gl; this.gl = gl;
this.uniforms = getUniformDefaultValue(); this.uniforms = getUniformDefaultValue();
@ -29,7 +33,7 @@ export class Renderer{
else throw e; else throw e;
} }
} }
init(){ prepare(){
const gl = this.gl; const gl = this.gl;
const position = [ const position = [
-0.5,-0.5, -0.5,-0.5,
@ -41,13 +45,17 @@ export class Renderer{
0,1,2, 0,1,2,
2,3,0 2,3,0
]; ];
this.positionBuffer = gl.createBuffer(); this.vao = gl.createVertexArray();
gl.bindBuffer(gl.ARRAY_BUFFER,this.positionBuffer); const posLoc = gl.getAttribLocation(this.program,"pos");
gl.bufferData(gl.ARRAY_BUFFER,new Float32Array(position),gl.STATIC_DRAW); gl.bindVertexArray(this.vao);
this.indexBuffer = gl.createBuffer(); this.positionBuffer = G.createVertexBuffer(gl,position);
gl.bindBuffer(gl.ELEMENT_ARRAY_BUFFER,this.indexBuffer); this.positionBuffer.bind(gl);
gl.bufferData(gl.ELEMENT_ARRAY_BUFFER,new Uint16Array(index),gl.STATIC_DRAW); gl.enableVertexAttribArray(posLoc);
gl.vertexAttribPointer(posLoc,2,gl.FLOAT,false,0,0);
this.indexBuffer = G.createIndexBuffer(gl,index);
this.indexBuffer.bind(gl);
this.settingUniform(this.uniforms); this.settingUniform(this.uniforms);
} }
useProgram(){ useProgram(){
@ -56,19 +64,19 @@ export class Renderer{
settingUniform(u:UniformSet){ settingUniform(u:UniformSet){
const gl = this.gl; const gl = this.gl;
this.uniforms = u; this.uniforms = u;
this.useProgram();
const location = gl.getUniformLocation(this.program, "u_color"); //u_color 변수 위치를 참조 const location = gl.getUniformLocation(this.program, "u_color"); //u_color 변수 위치를 참조
gl.uniform4f(location, this.uniforms.redcolor, 0.3, 0.8, 1.0); //해당 위치에 0.2, 0.3, 0.8, 1.0 데이터를 전달 gl.uniform4f(location, this.uniforms.redcolor, 0.3, 0.8, 1.0); //해당 위치에 0.2, 0.3, 0.8, 1.0 데이터를 전달
} }
draw(){ draw(){
const gl = this.gl; const gl = this.gl;
gl.clearColor(0,0,0,0); gl.clearColor(0,0,0,0);
gl.clear(gl.COLOR_BUFFER_BIT|gl.DEPTH_BUFFER_BIT); gl.clear(gl.COLOR_BUFFER_BIT);
gl.viewport(0,0,gl.canvas.width,gl.canvas.height); gl.viewport(0,0,gl.canvas.width,gl.canvas.height);
this.useProgram();
gl.enableVertexAttribArray(0); gl.bindVertexArray(this.vao);
gl.vertexAttribPointer(0,2,gl.FLOAT,false,0,0); this.indexBuffer.bind(gl);
gl.drawElements(gl.TRIANGLES,this.indexBuffer.count,gl.UNSIGNED_SHORT,0);
gl.drawElements(gl.TRIANGLES,6,gl.UNSIGNED_SHORT,0);
} }
} }

59
src/triangle_renderer.ts Normal file
View File

@ -0,0 +1,59 @@
import { RenderProgram } from "./program";
import {createProgramFromSource, ProgramError, ShaderError} from "./gl_util";
import { createIndexBuffer, createVertexBuffer, IndexBuffer, VertexBuffer } from "./glWrapper";
const vertex_shader_code = `#version 300 es
layout(location=0) in vec4 pos;
void main() {
gl_Position = pos;
}
`;
const frag_shader_code = `#version 300 es
precision highp float;
layout(location=0) out vec4 outColor;
void main() {
outColor = vec4(1.0,0.5,1.0,1.0);
}
`;
export class TriangleRenderer implements RenderProgram{
readonly program : WebGLProgram;
vao : WebGLVertexArrayObject;
indexBuffer : IndexBuffer;
constructor(gl: WebGL2RenderingContext){try{
this.program = createProgramFromSource(gl,vertex_shader_code,frag_shader_code);
//gl.useProgram(this.program);
}
catch(e){
if(e instanceof ShaderError){
console.log(e.message,"\n",e.info);
}
else if(e instanceof ProgramError){
console.log(e.message,"\n",e.info);
}
else throw e;
}
}
prepare(gl : WebGL2RenderingContext){
const vertex = createVertexBuffer(gl,[
0.5,0.5,
0.0,0.25,
0.0,0.75]);
this.indexBuffer = createIndexBuffer(gl,[0,1,2]);
const posLoc = gl.getAttribLocation(this.program,"pos");
this.vao = gl.createVertexArray();
gl.bindVertexArray(this.vao);
gl.enableVertexAttribArray(posLoc);
vertex.bind(gl);
gl.vertexAttribPointer(posLoc,2,gl.FLOAT,false,0,0);
this.indexBuffer.bind(gl);
}
draw(gl: WebGL2RenderingContext): void {
gl.useProgram(this.program);
gl.bindVertexArray(this.vao);
this.indexBuffer.bind(gl);
gl.drawElements(gl.TRIANGLES,this.indexBuffer.count,gl.UNSIGNED_SHORT,0);
}
}