slide bar

This commit is contained in:
monoid 2021-09-28 17:51:14 +09:00
parent 9922846acc
commit 515537ea68
9 changed files with 205 additions and 103 deletions

View File

@ -11,4 +11,28 @@ body{
top: 0;
left: 0;
position: fixed;
}
#drawer-button{
width: 30px;
height: 30px;
top: 5px;
right: 5px;
position: fixed;
background-color: rgb(0, 0, 0,0.5);
border-radius: 5px;
color: white;
}
#drawer{
position: fixed;
width: 350px;
height: calc(90vh - 70px);
top: 70px;
right: -380px;
transition: right 0.4s ease;
background-color: white;
box-shadow: black 5px 5px 10px 0px;
border-radius: 5px;
padding: 15px;
}

View File

@ -5,9 +5,17 @@
<meta charset="utf-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<link rel="stylesheet" href="index.css">
<script src="./index.ts" defer></script>
<script src="./index.tsx" defer></script>
</head>
<body>
<canvas id="canvas" width="500" height="500"></canvas>
<div id="drawer-button">
<svg xmlns="http://www.w3.org/2000/svg" fill="currentColor" class="bi bi-list" viewBox="0 0 16 16">
<path fill-rule="evenodd" d="M2.5 12a.5.5 0 0 1 .5-.5h10a.5.5 0 0 1 0 1H3a.5.5 0 0 1-.5-.5zm0-4a.5.5 0 0 1 .5-.5h10a.5.5 0 0 1 0 1H3a.5.5 0 0 1-.5-.5zm0-4a.5.5 0 0 1 .5-.5h10a.5.5 0 0 1 0 1H3a.5.5 0 0 1-.5-.5z"/>
</svg>
</div>
<div id="drawer">
</div>
</body>
</html>

View File

@ -1,95 +0,0 @@
/// <reference path="node_modules/webgl-strict-types/index.d.ts" />
import {createProgramFromSource, ProgramError, ShaderError} from "./src/gl_util";
/// <reference path="./src/glsl.d.ts" />
import vert_src from "./src/vertex";
import frag_src from "./src/fragment";
function findCanvas(){
const canvas = document.querySelector("canvas");
if(canvas === null){
console.error("couldn't find canvas");
throw new Error("canvas is null");
}
return canvas;
}
function getGLContext(canvas : HTMLCanvasElement){
const gl = canvas.getContext("webgl2") as any as WebGL2RenderingContextStrict|null;
if(gl === null){
console.error("webgl2 is not supported!");
throw new Error("webgl2 not supported");
}
return gl;
}
class Renderer{
gl : WebGL2RenderingContextStrict;
constructor(gl: WebGL2RenderingContextStrict){
this.gl = gl;
}
init(){
const gl = this.gl;
let program: WebGLProgram;
try{
program = createProgramFromSource(gl,vert_src,frag_src);
gl.useProgram(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;
}
const position = [
-0.5,-0.5,
0.5,-0.5,
0.5,0.5,
-0.5,0.5
];
const index = [
0,1,2,
2,3,0
];
const positionBuffer = gl.createBuffer();
gl.bindBuffer(gl.ARRAY_BUFFER,positionBuffer);
gl.bufferData(gl.ARRAY_BUFFER,new Float32Array(position),gl.STATIC_DRAW);
const indexBuffer = gl.createBuffer();
gl.bindBuffer(gl.ELEMENT_ARRAY_BUFFER,indexBuffer);
gl.bufferData(gl.ELEMENT_ARRAY_BUFFER,new Uint16Array(index),gl.STATIC_DRAW);
let location = gl.getUniformLocation(program, "u_color"); //u_color 변수 위치를 참조
gl.uniform4f(location, 0.8, 0.3, 0.8, 1.0); //해당 위치에 0.2, 0.3, 0.8, 1.0 데이터를 전달
}
draw(){
const gl = this.gl;
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);
}
}
function main(){
const canvas = findCanvas();
const gl = getGLContext(canvas);
const renderer = new Renderer(gl);
renderer.init()
window.addEventListener("resize",(e)=>{
e.preventDefault();
canvas.width = document.body.clientWidth;
canvas.height = document.body.clientHeight;
renderer.draw();
});
canvas.width = document.body.clientWidth;
canvas.height = document.body.clientHeight;
renderer.draw();
}
main();

60
index.tsx Normal file
View File

@ -0,0 +1,60 @@
import { Renderer } from './src/renderer';
import React from 'react';
import ReactDOM from 'react-dom';
import { MenuBar } from "./src/menu";
function findCanvas(){
const canvas = document.querySelector("canvas");
if(canvas === null){
console.error("couldn't find canvas");
throw new Error("canvas is null");
}
return canvas;
}
function getGLContext(canvas : HTMLCanvasElement){
const gl = canvas.getContext("webgl2") as any as WebGL2RenderingContext|null;
if(gl === null){
console.error("webgl2 is not supported!");
throw new Error("webgl2 not supported");
}
return gl;
}
function setupButton(){
let toggle = false;
const button = document.querySelector("#drawer-button") as HTMLDivElement;
const drawer = document.querySelector("#drawer") as HTMLDivElement;
button.addEventListener("click",()=>{
toggle = !toggle;
if(toggle){
drawer.style.right = "0px";
}
else{
drawer.style.right = "";
}
});
}
function main(){
setupButton();
const canvas = findCanvas();
const gl = getGLContext(canvas);
const renderer = new Renderer(gl);
renderer.init();
ReactDOM.render(<MenuBar u={renderer.uniforms}
onUniformChange={(u)=>{renderer.settingUniform(u); renderer.draw();}} />
,document.getElementById("drawer"));
window.addEventListener("resize",(e)=>{
e.preventDefault();
canvas.width = document.body.clientWidth;
canvas.height = document.body.clientHeight;
renderer.draw();
});
canvas.width = document.body.clientWidth;
canvas.height = document.body.clientHeight;
renderer.draw();
}
main();

View File

@ -10,7 +10,13 @@
"author": "",
"license": "ISC",
"dependencies": {
"parcel-bundler": "^1.12.5"
"@emotion/react": "^11.4.1",
"@emotion/styled": "^11.3.0",
"@mui/material": "^5.0.1",
"@types/react": "^17.0.24",
"parcel-bundler": "^1.12.5",
"react": "^17.0.2",
"react-dom": "^17.0.2"
},
"devDependencies": {
"glslify-bundle": "^5.1.1",

View File

@ -1,6 +1,3 @@
import GL = WebGLRenderingContextStrict;
import GL2 = WebGL2RenderingContextStrict;
export class ShaderError extends Error{
constructor(
readonly info:string
@ -20,7 +17,7 @@ export class ProgramError extends Error{
/***
* compile shader
*/
export function compileShader(gl:GL2, source:string, type: GL.ShaderType): WebGLShader{
export function compileShader(gl:WebGL2RenderingContext, source:string, type: GLenum): WebGLShader{
const shader = gl.createShader(type);
gl.shaderSource(shader,source);
gl.compileShader(shader);
@ -32,7 +29,7 @@ export function compileShader(gl:GL2, source:string, type: GL.ShaderType): WebGL
return shader;
}
export function createProgram(gl:GL2, vertex:WebGLShader,frag:WebGLShader){
export function createProgram(gl:WebGL2RenderingContext, vertex:WebGLShader,frag:WebGLShader){
const program = gl.createProgram();
gl.attachShader(program,vertex);
gl.attachShader(program,frag);
@ -46,7 +43,7 @@ export function createProgram(gl:GL2, vertex:WebGLShader,frag:WebGLShader){
}
return program;
}
export function createProgramFromSource(gl:GL2, vert:string,frag:string){
export function createProgramFromSource(gl:WebGL2RenderingContext, vert:string,frag:string){
const vert_shader = compileShader(gl,vert,gl.VERTEX_SHADER);
const frag_shader = compileShader(gl,frag,gl.FRAGMENT_SHADER);
return createProgram(gl,vert_shader,frag_shader);

19
src/menu.tsx Normal file
View File

@ -0,0 +1,19 @@
import * as React from 'react';
import Slider from "@mui/material/Slider";
import Typograpy from "@mui/material/Typography";
import {UniformSet} from "./uniform";
export function MenuBar(prop:{u:UniformSet,onUniformChange:(u:UniformSet)=>void}){
const [uniform,setUniform] = React.useState(prop.u);
const onRedChange = (_,v)=>{
setUniform({...uniform,redcolor:v/100});
};
React.useEffect(()=>{
prop.onUniformChange(uniform);
})
const a = uniform.redcolor*100;
return (<div>
<Typograpy variant="h4">Uniform</Typograpy>
<Slider aria-label="Small" valueLabelDisplay="auto" onChange={onRedChange} value={a}></Slider>
</div>);
}

74
src/renderer.ts Normal file
View File

@ -0,0 +1,74 @@
import {createProgramFromSource, ProgramError, ShaderError} from "./gl_util";
/// <reference path="./glsl.d.ts" />
import vert_src from "./vertex.vert";
import frag_src from "./fragment.frag";
import { getUniformDefaultValue, UniformSet } from "./uniform";
export class Renderer{
gl : WebGL2RenderingContext;
uniforms : UniformSet;
program: WebGLProgram;
positionBuffer: WebGLBuffer;
indexBuffer: WebGLBuffer;
constructor(gl: WebGL2RenderingContext){
this.gl = gl;
this.uniforms = getUniformDefaultValue();
try{
this.program = createProgramFromSource(gl,vert_src,frag_src);
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;
}
}
init(){
const gl = this.gl;
const position = [
-0.5,-0.5,
0.5,-0.5,
0.5,0.5,
-0.5,0.5
];
const index = [
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.indexBuffer = gl.createBuffer();
gl.bindBuffer(gl.ELEMENT_ARRAY_BUFFER,this.indexBuffer);
gl.bufferData(gl.ELEMENT_ARRAY_BUFFER,new Uint16Array(index),gl.STATIC_DRAW);
this.settingUniform(this.uniforms);
}
useProgram(){
this.gl.useProgram(this.program);
}
settingUniform(u:UniformSet){
const gl = this.gl;
this.uniforms = u;
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.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);
}
}

9
src/uniform.ts Normal file
View File

@ -0,0 +1,9 @@
export type UniformSet = {
redcolor:number
};
export function getUniformDefaultValue():UniformSet{
return {
redcolor:0.5,
}
}