001/* 002 * Renderer 7. The MIT License. 003 * Copyright (c) 2022 rlkraft@pnw.edu 004 * See LICENSE for details. 005*/ 006 007package renderer.pipeline; 008 009import renderer.scene.*; 010import renderer.scene.primitives.Point; 011import renderer.framebuffer.*; 012import static renderer.pipeline.PipelineLogger.*; 013 014import java.awt.Color; 015 016/** 017 Rasterize a clipped {@link Point} into shaded pixels 018 in a {@link FrameBuffer.Viewport}, but do not rasterize 019 any part of the {@link Point} that is not contained in 020 the {@link Camera}'s view rectangle. 021*/ 022public class Rasterize_Clip_Point 023{ 024 /** 025 Rasterize a {@link Point} into shaded pixels 026 in a {@link FrameBuffer.Viewport}. 027 028 @param model {@link Model} that the {@link Point} {@code pt} comes from 029 @param pt {@code Point} to rasterize into the {@code FrameBuffer.Viewport} 030 @param vp {@link FrameBuffer.Viewport} to hold rasterized, shaded pixels 031 */ 032 public static void rasterize(final Model model, 033 final Point pt, 034 final FrameBuffer.Viewport vp) 035 { 036 final String CLIPPED = " : Clipped"; 037 final String NOT_CLIPPED = ""; 038 039 // Get the viewport's background color. 040 final Color bg = vp.bgColorVP; 041 042 // Make local copies of several values. 043 final int w = vp.getWidthVP(); 044 final int h = vp.getHeightVP(); 045 046 final int vIndex = pt.vIndexList.get(0); 047 final Vertex v = model.vertexList.get(vIndex); 048 049 final int cIndex = pt.cIndexList.get(0); 050 final float[] c = model.colorList.get(cIndex).getRGBComponents(null); 051 float r = c[0], g = c[1], b = c[2]; 052 053 if (Rasterize.doGamma) 054 { 055 // Apply gamma-encoding (gamma-compression) to the two colors. 056 // https://www.scratchapixel.com/lessons/digital-imaging/digital-images 057 // http://blog.johnnovak.net/2016/09/21/what-every-coder-should-know-about-gamma/ 058 final double gammaInv = 1.0 / Rasterize.GAMMA; 059 r = (float)Math.pow(r, gammaInv); 060 g = (float)Math.pow(g, gammaInv); 061 b = (float)Math.pow(b, gammaInv); 062 } 063 064 // Transform the vertex to the pixel-plane coordinate system. 065 double x = 0.5 + w/2.001 * (v.x + 1); // x_pp = 0.5 + w/2 * (x_p+1) 066 double y = 0.5 + h/2.001 * (v.y + 1); // y_pp = 0.5 + h/2 * (y_p+1) 067 // NOTE: Notice the 2.001 fudge factor in the last two equations. 068 // This is explained on page 142 of 069 // "Jim Blinn's Corner: A Trip Down The Graphics Pipeline" 070 // by Jim Blinn, 1996, Morgan Kaufmann Publishers. 071 072 if (Rasterize.debug) 073 { 074 logMessage(String.format("(x_pp, y_pp) = (%9.4f, %9.4f)", x, y)); 075 } 076 077 // Round the point's coordinates to the nearest logical pixel. 078 x = Math.round( x ); 079 y = Math.round( y ); 080 081 final int radius = pt.radius; 082 083 for (int y_ = (int)y - radius; y_ <= (int)y + radius; ++y_) 084 { 085 for (int x_ = (int)x - radius; x_ <= (int)x + radius; ++x_) 086 { 087 if (Rasterize.debug) 088 { 089 final String clippedMessage; 090 if (x_ > 0 && x_ <= w && y_ > 0 && y_ <= h) // clipping test 091 { 092 clippedMessage = NOT_CLIPPED; 093 } 094 else 095 { 096 clippedMessage = CLIPPED; 097 } 098 logPixel(clippedMessage, x, y, x_ - 1, h - y_, r, g, b, vp); 099 } 100 // Log the pixel before setting it so that an array out- 101 // of-bounds error will be right after the pixel's address. 102 103 if (x_ > 0 && x_ <= w && y_ > 0 && y_ <= h) // clipping test 104 { 105 vp.setPixelVP(x_ - 1, h - y_, new Color(r, g, b)); 106 } 107 } 108 } 109 } 110 111 112 113 // Private default constructor to enforce noninstantiable class. 114 // See Item 4 in "Effective Java", 3rd Ed, Joshua Bloch. 115 private Rasterize_Clip_Point() { 116 throw new AssertionError(); 117 } 118}