Interactive 3D Sphere Renderer in Vue with WebGL
This challenge asks you to build a simple interactive 3D sphere renderer within a Vue component using WebGL. The sphere should be visually appealing, respond to mouse movements to rotate, and have a basic lighting model. This exercise combines front-end framework proficiency (Vue) with low-level graphics programming (WebGL), demonstrating a practical application of both.
Problem Description
You need to create a Vue component that renders a 3D sphere using WebGL. The sphere should be initially centered in the component's canvas and should rotate continuously when the mouse is moved within the component's bounds. The sphere should have a basic diffuse lighting model, with a single directional light source.
Key Requirements:
- Vue Component: The solution must be a valid Vue component.
- WebGL Canvas: The component must create and manage a WebGL rendering context within a
<canvas>element. - Sphere Geometry: The sphere should be rendered using a sufficient number of vertices to appear smooth (e.g., at least 32 segments in each direction).
- Shaders: You must implement basic vertex and fragment shaders for rendering the sphere. The shaders should handle vertex transformations, lighting, and color.
- Mouse Interaction: The sphere should rotate around the X and Y axes based on the mouse's position relative to the center of the canvas. The rotation speed should be proportional to the mouse's distance from the center.
- Lighting: Implement a simple directional light source. The light direction should be fixed (e.g., pointing downwards).
- Error Handling: Basic error handling for WebGL initialization is expected.
Expected Behavior:
- The component should render a visually appealing 3D sphere within the canvas.
- Moving the mouse within the canvas should cause the sphere to rotate smoothly.
- The sphere should be lit, with visible shading based on the light direction.
- The component should handle WebGL initialization errors gracefully.
Edge Cases to Consider:
- Canvas size changes: The component should adapt to different canvas sizes.
- Browser support: Ensure the code works in modern browsers with WebGL support.
- Performance: While not a primary focus, avoid excessive calculations that could lead to poor performance.
Examples
Example 1:
Input: Initial mouse position at the center of the canvas. Canvas size: 500x500.
Output: A static, lit sphere centered in the canvas.
Explanation: The sphere is initially not rotating because the mouse is at the center.
Example 2:
Input: Mouse position at (100, 150) on a 500x500 canvas.
Output: The sphere is rotating around the X and Y axes, with the rotation speed proportional to the distance from the center.
Explanation: The mouse position triggers rotation. The further the mouse is from the center, the faster the rotation.
Example 3:
Input: Canvas size changes from 500x500 to 800x600.
Output: The sphere remains centered within the new canvas dimensions, and the rotation behavior remains consistent.
Explanation: The component adapts to the new canvas size, maintaining the sphere's position and rotation.
Constraints
- Canvas Size: The component should be able to handle canvas sizes ranging from 200x200 to 1000x800 pixels.
- Shader Complexity: Keep the shaders relatively simple. Focus on demonstrating the core concepts of vertex transformation, lighting, and color. Avoid complex textures or advanced lighting techniques.
- Performance: The rendering should maintain a frame rate of at least 30 FPS on a reasonably modern computer.
- Dependencies: You are allowed to use only standard WebGL APIs and Vue.js. No external WebGL libraries are permitted.
Notes
- Start by setting up the WebGL context and creating the canvas within the Vue component.
- Consider using a
refto access the canvas element directly. - The vertex shader should transform the sphere's vertices into clip space.
- The fragment shader should calculate the diffuse lighting contribution and apply it to the sphere's color.
- Use
requestAnimationFramefor smooth animation. - Think about how to normalize mouse coordinates to a range between -1 and 1 for rotation calculations.
- Remember to handle WebGL errors appropriately. Check for
gl.getError()after WebGL calls.