| | import streamlit as st |
| | import json |
| | from pathlib import Path |
| |
|
| | st.set_page_config(page_title="Shader + Comments JSON", layout="wide") |
| |
|
| | st.title("🌀 Shader + Comments (Hugging Face Ready)") |
| |
|
| | |
| | |
| | |
| | DATA_DIR = Path("./data") |
| | DATA_DIR.mkdir(exist_ok=True) |
| | COMMENTS_FILE = DATA_DIR / "comments.json" |
| |
|
| | |
| | if COMMENTS_FILE.exists(): |
| | with open(COMMENTS_FILE, "r") as f: |
| | comments = json.load(f) |
| | else: |
| | comments = [] |
| |
|
| | |
| | |
| | |
| | shader_code_default = """ |
| | precision mediump float; |
| | uniform vec2 iResolution; |
| | uniform float iTime; |
| | |
| | void mainImage(out vec4 fragColor, in vec2 fragCoord) { |
| | vec2 uv = fragCoord / iResolution.xy; |
| | vec3 col = 0.5 + 0.5*cos(iTime + uv.xyx + vec3(0,2,4)); |
| | fragColor = vec4(col,1.0); |
| | } |
| | void main() { mainImage(gl_FragColor, gl_FragCoord.xy); } |
| | """ |
| |
|
| | latest_shader = shader_code_default |
| | for c in reversed(comments): |
| | if c.get("type") == "shader": |
| | latest_shader = c["content"] |
| | break |
| |
|
| | |
| | |
| | |
| | shader_code = st.text_area("Shader Code (GLSL Fragment Shader)", latest_shader, height=250) |
| |
|
| | |
| | |
| | |
| | html_code = f""" |
| | <canvas id="glcanvas" width="800" height="500"></canvas> |
| | <script> |
| | const canvas = document.getElementById('glcanvas'); |
| | const gl = canvas.getContext('webgl'); |
| | if (!gl) {{ |
| | alert('WebGL not supported'); |
| | }} |
| | |
| | const vertCode = ` |
| | attribute vec4 a_position; |
| | void main() {{ |
| | gl_Position = a_position; |
| | }} |
| | `; |
| | |
| | const fragCode = `{shader_code}`; |
| | |
| | function createShader(gl, type, source) {{ |
| | const shader = gl.createShader(type); |
| | gl.shaderSource(shader, source); |
| | gl.compileShader(shader); |
| | if (!gl.getShaderParameter(shader, gl.COMPILE_STATUS)) {{ |
| | alert(gl.getShaderInfoLog(shader)); |
| | }} |
| | return shader; |
| | }} |
| | |
| | const vertexShader = createShader(gl, gl.VERTEX_SHADER, vertCode); |
| | const fragmentShader = createShader(gl, gl.FRAGMENT_SHADER, fragCode); |
| | |
| | const program = gl.createProgram(); |
| | gl.attachShader(program, vertexShader); |
| | gl.attachShader(program, fragmentShader); |
| | gl.linkProgram(program); |
| | gl.useProgram(program); |
| | |
| | const positionBuffer = gl.createBuffer(); |
| | gl.bindBuffer(gl.ARRAY_BUFFER, positionBuffer); |
| | gl.bufferData(gl.ARRAY_BUFFER, new Float32Array([ |
| | -1, -1, 1, -1, -1, 1, |
| | -1, 1, 1, -1, 1, 1 |
| | ]), gl.STATIC_DRAW); |
| | |
| | const positionLoc = gl.getAttribLocation(program, "a_position"); |
| | gl.enableVertexAttribArray(positionLoc); |
| | gl.vertexAttribPointer(positionLoc, 2, gl.FLOAT, false, 0, 0); |
| | |
| | const iResolution = gl.getUniformLocation(program, "iResolution"); |
| | const iTime = gl.getUniformLocation(program, "iTime"); |
| | |
| | function render(time) {{ |
| | gl.uniform2f(iResolution, canvas.width, canvas.height); |
| | gl.uniform1f(iTime, time * 0.001); |
| | gl.drawArrays(gl.TRIANGLES, 0, 6); |
| | requestAnimationFrame(render); |
| | }} |
| | |
| | requestAnimationFrame(render); |
| | </script> |
| | """ |
| |
|
| | st.components.v1.html(html_code, height=520) |
| |
|
| | |
| | |
| | |
| | st.markdown("---") |
| | st.subheader("💬 Comments / Add New Shader") |
| |
|
| | |
| |
|
| | with st.form("comment_form", clear_on_submit=True): |
| | user_name = st.text_input("Your name", "") |
| | user_content = st.text_area("Content", "", height=80) |
| | submitted = st.form_submit_button("Submit") |
| |
|
| | if submitted and user_content.strip(): |
| | new_comment = { |
| | "name": user_name or "Anonymous", |
| | "content": user_content, |
| | |
| | } |
| | comments.append(new_comment) |
| |
|
| | |
| | with open(COMMENTS_FILE, "w") as f: |
| | json.dump(comments, f, indent=2) |
| |
|
| | st.success("Saved!") |
| |
|
| | |
| |
|
| | |
| | for c in reversed(comments): |
| | st.markdown(f"**{c['name']}**: {c['content']}") |