From ac7b2f400a609a6487f6dda88b97948c88c250b4 Mon Sep 17 00:00:00 2001 From: monoid Date: Sat, 2 Oct 2021 19:13:52 +0900 Subject: [PATCH] Drawing Multiple Object --- index.tsx | 16 ++++++++--- src/app.ts | 28 +++++++++++++++++++ src/glWrapper.ts | 54 ++++++++++++++++++++++++++++++++++++ src/menu.tsx | 4 +-- src/program.ts | 4 +++ src/renderer.ts | 40 ++++++++++++++++----------- src/triangle_renderer.ts | 59 ++++++++++++++++++++++++++++++++++++++++ 7 files changed, 183 insertions(+), 22 deletions(-) create mode 100644 src/app.ts create mode 100644 src/glWrapper.ts create mode 100644 src/program.ts create mode 100644 src/triangle_renderer.ts diff --git a/index.tsx b/index.tsx index 3b427b7..6fef68c 100644 --- a/index.tsx +++ b/index.tsx @@ -1,9 +1,10 @@ -import { Renderer } from './src/renderer'; +import { Renderer2D } from './src/renderer'; import React from 'react'; import ReactDOM from 'react-dom'; import { MenuBar } from "./src/menu"; +import { TriangleRenderer } from './src/triangle_renderer'; function findCanvas(){ const canvas = document.querySelector("canvas"); @@ -42,19 +43,26 @@ function main(){ setupButton(); const canvas = findCanvas(); const gl = getGLContext(canvas); - const renderer = new Renderer(gl); - renderer.init(); + const renderer = new Renderer2D(gl); + const trenderer = new TriangleRenderer(gl); + renderer.prepare(); + trenderer.prepare(gl); + ReactDOM.render({renderer.settingUniform(u); renderer.draw();}} /> + onUniformChange={(u)=>{renderer.settingUniform(u); renderer.draw(); + trenderer.draw(gl); + }} /> ,document.getElementById("drawer")); window.addEventListener("resize",(e)=>{ e.preventDefault(); canvas.width = document.body.clientWidth; canvas.height = document.body.clientHeight; renderer.draw(); + trenderer.draw(gl); }); canvas.width = document.body.clientWidth; canvas.height = document.body.clientHeight; renderer.draw(); + trenderer.draw(gl); } main(); \ No newline at end of file diff --git a/src/app.ts b/src/app.ts new file mode 100644 index 0000000..960d764 --- /dev/null +++ b/src/app.ts @@ -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(); + } +}; \ No newline at end of file diff --git a/src/glWrapper.ts b/src/glWrapper.ts new file mode 100644 index 0000000..59e35d4 --- /dev/null +++ b/src/glWrapper.ts @@ -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); +} \ No newline at end of file diff --git a/src/menu.tsx b/src/menu.tsx index 51ad7d2..5b7a09f 100644 --- a/src/menu.tsx +++ b/src/menu.tsx @@ -10,10 +10,10 @@ export function MenuBar(prop:{u:UniformSet,onUniformChange:(u:UniformSet)=>void} }; React.useEffect(()=>{ prop.onUniformChange(uniform); - }) + }); const a = uniform.redcolor*100; return (
Uniform - +
); } \ No newline at end of file diff --git a/src/program.ts b/src/program.ts new file mode 100644 index 0000000..f6c069b --- /dev/null +++ b/src/program.ts @@ -0,0 +1,4 @@ + +export interface RenderProgram{ + draw(gl:WebGL2RenderingContext):void; +}; \ No newline at end of file diff --git a/src/renderer.ts b/src/renderer.ts index 45bc38b..45fe998 100644 --- a/src/renderer.ts +++ b/src/renderer.ts @@ -4,14 +4,18 @@ import {createProgramFromSource, ProgramError, ShaderError} from "./gl_util"; import vert_src from "./vertex.vert"; import frag_src from "./fragment.frag"; +import { RenderProgram } from "./program"; +import * as G from "./glWrapper"; import { getUniformDefaultValue, UniformSet } from "./uniform"; -export class Renderer{ +export class Renderer2D implements RenderProgram{ gl : WebGL2RenderingContext; uniforms : UniformSet; program: WebGLProgram; - positionBuffer: WebGLBuffer; - indexBuffer: WebGLBuffer; + + vao: WebGLVertexArrayObject; + positionBuffer: G.VertexBuffer; + indexBuffer: G.IndexBuffer; constructor(gl: WebGL2RenderingContext){ this.gl = gl; this.uniforms = getUniformDefaultValue(); @@ -29,7 +33,7 @@ export class Renderer{ else throw e; } } - init(){ + prepare(){ const gl = this.gl; const position = [ -0.5,-0.5, @@ -41,13 +45,17 @@ export class Renderer{ 0,1,2, 2,3,0 ]; - this.positionBuffer = gl.createBuffer(); - gl.bindBuffer(gl.ARRAY_BUFFER,this.positionBuffer); - gl.bufferData(gl.ARRAY_BUFFER,new Float32Array(position),gl.STATIC_DRAW); + this.vao = gl.createVertexArray(); + const posLoc = gl.getAttribLocation(this.program,"pos"); + gl.bindVertexArray(this.vao); + + this.positionBuffer = G.createVertexBuffer(gl,position); + this.positionBuffer.bind(gl); + gl.enableVertexAttribArray(posLoc); + gl.vertexAttribPointer(posLoc,2,gl.FLOAT,false,0,0); - this.indexBuffer = gl.createBuffer(); - gl.bindBuffer(gl.ELEMENT_ARRAY_BUFFER,this.indexBuffer); - gl.bufferData(gl.ELEMENT_ARRAY_BUFFER,new Uint16Array(index),gl.STATIC_DRAW); + this.indexBuffer = G.createIndexBuffer(gl,index); + this.indexBuffer.bind(gl); this.settingUniform(this.uniforms); } useProgram(){ @@ -56,19 +64,19 @@ export class Renderer{ settingUniform(u:UniformSet){ const gl = this.gl; this.uniforms = u; + this.useProgram(); 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 데이터를 전달 } draw(){ const gl = this.gl; 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.enableVertexAttribArray(0); - gl.vertexAttribPointer(0,2,gl.FLOAT,false,0,0); - - gl.drawElements(gl.TRIANGLES,6,gl.UNSIGNED_SHORT,0); + this.useProgram(); + gl.bindVertexArray(this.vao); + this.indexBuffer.bind(gl); + gl.drawElements(gl.TRIANGLES,this.indexBuffer.count,gl.UNSIGNED_SHORT,0); } } \ No newline at end of file diff --git a/src/triangle_renderer.ts b/src/triangle_renderer.ts new file mode 100644 index 0000000..3a5b70f --- /dev/null +++ b/src/triangle_renderer.ts @@ -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); + } +} \ No newline at end of file