E D R S I H C RSS
ID
Password
Join
๋‹ค๋ฅธ ์‚ฌ๋žŒ์„ ์„ค๋“ํ•˜๋Š” ๊ฐ€์žฅ ์ข‹์€ ๋„๊ตฌ๋Š” ์šฐ๋ฆฌ์˜ ๊ท€. ์ฆ‰ ์ƒ๋Œ€ํŽธ ๋ง์— ์šฐ์„  ๊ท€๋ฅผ ๊ธฐ์šธ์—ฌ ๋“ฃ๋Š” ๊ฒƒ. โ€•๋”˜ ๋Ÿฌ์Šคํฌ(ๅ‰ ็พŽ๊ตญ๋ฌด์žฅ๊ด€)

๏ปฟ * ์›๋ฌธ ๋งํฌ : [http]http://www.cgshaders.org/articles/interview_davidkirk.php

๊ฐœ์š” #

๋ฐ์ด๋น— ์ปคํฌ(NVIDIA์˜ ๋ฉ”์ธ ๊ฐœ๋ฐœ์ž(Chief Scientist))๊ณผ Cg์™€ ์ด๊ฒƒ์ด ๊ทธ๋ž˜ํ”ฝ ํ”„๋กœ๊ทธ๋ž˜๋ฐ ์ปค๋ฎค๋‹ˆํ‹ฐ์— ์–ด๋–ค ์˜๋ฏธ๊ฐ€ ์žˆ๋Š”์ง€์— ๋Œ€ํ•ด์„œ ์•ฝ๊ฐ„ ๋Œ€ํ™”ํ•  ๊ธฐํšŒ๊ฐ€ ์žˆ์—ˆ๋‹ค. ์šฐ๋ฆฌ์˜ ์งˆ๋ฌธ์— ๋Œ€ํ•ด์„œ ๋‹ต๋ณ€ํ•  ์‹œ๊ฐ„์„ ๋งˆ๋ จํ•ด ์ค€ ๋ฐ์ด๋น—์—๊ฒŒ ๊ฐ์‚ฌํ•œ๋‹ค.

์‹ค์ œ๋กœ Cg๊ฐ€ ๋ฌด์—‡์ด๋ฉฐ, ์™œ ๊ฐœ๋ฐœ์ž๋“ค์ด ์ด๊ฒƒ์— ๊ด€์‹ฌ์„ ๊ฐ€์งˆ ๊ฒƒ์ธ์ง€ ์•Œ๋ ค์ฃผ์‹ญ์‹œ์š”. #

Cg๋Š” ๊ทธ๋ž˜ํ”ฝ์Šค๋ฅผ ์œ„ํ•œ C ์–ธ์–ด์ž…๋‹ˆ๋‹ค. ์•„์ด๋””์–ด๋Š” ๊ณผ๊ฑฐ์— ์š”๊ตฌ๋˜์—ˆ๋˜ GPU์˜ ํ”„๋กœ๊ทธ๋ž˜๋ฐ์— ์žˆ์–ด์„œ ์ €๋ ˆ๋ฒจ ์–ด์…ˆ๋ธ”๋ฆฌ ์ฝ”๋”ฉ์„ ์‚ฌ์šฉํ•˜๊ธฐ๋ณด๋‹ค๋Š” ์ƒ์œ„ ๋ ˆ๋ฒจ์˜ ์–ธ์–ด๋ฅผ ์‚ฌ์šฉํ•˜์ž๊ณ  ํ•˜๋Š” ๊ฒƒ์ด์—ˆ์Šต๋‹ˆ๋‹ค. ์–ด์…ˆ๋ธ”๋ฆฌ ์–ธ์–ด ํ”„๋กœ๊ทธ๋ž˜๋ฐ์€ ์งง์€ ์ฝ”๋”ฉ์—๋Š” ์ ํ•ฉํ•˜๋‚˜, GPU๊ฐ€ ์ ์  ๋” ๊ณ ์ˆ˜์ค€์œผ๋กœ ํ”„๋กœ๊ทธ๋ž˜๋ฐ ๊ฐ€๋Šฅํ•˜๊ฒŒ ์ง„ํ™”๋˜๊ณ  ๋” ๊ธธ๊ณ  ์œตํ†ต์„ฑ์žˆ๋Š” ํ”„๋กœ๊ทธ๋žจ์„ ์ง€์›ํ•จ์— ๋”ฐ๋ผ ์–ด์…ˆ๋ธ”๋ฆฌ๋ฅผ ์‚ฌ์šฉํ•˜๋Š” ๊ฒƒ์€ ์‚ฌ์šฉํ•˜๊ธฐ ๊นŒ๋‹ค๋กญ๊ฒŒ ๋˜์—ˆ์Šต๋‹ˆ๋‹ค. ์ƒ์œ„ ๋ ˆ๋ฒจ ์–ธ์–ด ํ”„๋กœ๊ทธ๋ž˜๋ฐ์€ ๊ฐœ๋ฐœ์ž๋กœ ํ•˜์—ฌ๊ธˆ ๊ทธ๋‹ค์ง€ ๋งŽ์€ ํ•˜๋“œ์›จ์–ด ๋ช…๋ น์„ ์Šต๋“ํ•˜์ง€ ์•Š๊ณ ์„œ๋„, ๋”์šฑ ์ง์ ‘์ ์œผ๋กœ ์ž‘์—…์„ ํ• ์ˆ˜ ์žˆ๋„๋ก ํ•ด์ค๋‹ˆ๋‹ค. ๊ฐœ๋ฐœ์ž๋Š” ๋ณด๋‹ค ์‰ฝ๊ฒŒ ํ”„๋กœ๊ทธ๋žจ๋“ค์„ ์ƒ์„ฑํ•˜๊ณ  ์ˆ˜์ •ํ•  ์ˆ˜ ์žˆ๊ฒŒ ๋˜๋ฉฐ, ๊ทธ ํ”„๋กœ๊ทธ๋žจ์€ ์–ด๋–ค ํ•˜๋“œ์›จ์–ด์—์„œ๋„ ์ž˜ ์‹คํ–‰๋˜๋„๋ก ์ปดํŒŒ์ผ ๋  ๊ฒƒ์ž…๋‹ˆ๋‹ค. (์—ญ์ฃผ : ์นด๋“œ์— ๊ด€๊ณ„์—†์ด ํ•œ๋ฒˆ์˜ ์ปดํŒŒ์ผ๋กœ ํ™œ์šฉ์ด ๊ฐ€๋Šฅํ•˜๋‹ค๋ผ๋Š” ๊ฒƒ์„ ์˜๋ฏธํ•˜๋Š” ๋“ฏํ•จ.)

๊ฐœ๋ฐœ์ž๊ฐ€ OpenGL์ด๋‚˜ Direct3D์ค‘ ์–ด๋А ์ชฝ์„ ์‚ฌ์šฉ์ค‘์— ์žˆ๋Š”์ง€ ์—ฌ๋ถ€๊ฐ€ Cg๋ฅผ ์‚ฌ์šฉํ•˜๋Š”๋ฐ ์˜ํ–ฅ์ด ์žˆ์Šต๋‹ˆ๊นŒ? #

์•„๋‹™๋‹ˆ๋‹ค. ๋ช‡๋ช‡ ์šฐ์ฃผ์ ์ด๊ฑฐ๋‚˜ ์ข…๊ต์ ์ธ ๋œป์œผ๋กœ ๋ฌผ์–ด๋ณด๋Š” ๊ฒƒ์ด ์•„๋‹ˆ๋ผ๋ฉด ๋ง์ด์ฃ . (์—ญ์ฃผ : DX๋‚˜ GL ํ•œ์ชฝ๋งŒ์„ ์ข‹์•„ํ•˜์ง€ ์•Š๋Š”๋‹ค๋Š” ์˜๋ฏธ์ธ ๋“ฏ...) :-) Cg๊ฐ€ ํ‘œ์ค€ OpenGL์˜ ์ตœ์ƒ์ธต์˜ ๋ ˆ์ด์–ด์— ๋†“์—ฌ์žˆ์œผ๋ฉฐ, ๋˜ํ•œ directX8๊ณผ directX9์—์„œ๋„ ์ตœ์ƒ์ธต์˜ ๋ ˆ์ด์–ด์— ๋†“์—ฌ์žˆ๊ธฐ ๋•Œ๋ฌธ์—, Cg ํ”„๋กœ๊ทธ๋žจ์€ ๋…๋ฆฝ์ ์ธ API ๊ธฐ๋ฐ˜ํ•˜์— ์ž‘์„ฑ๋  ์ˆ˜ ์žˆ์œผ๋ฉฐ ๋ณ€๊ฒฝ ์—†์ด ์–‘์ชฝ API์ƒ์—์„œ ์‹คํ–‰๋  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค.

How flexible is Cg really? What are two unrelated examples of what you can easily do with Cg that would be a major pain with the assembly interface, or just plain impossible with the fixed-function pipeline? #

One of the important things you can do with Cg that's a pain with the assembly interface is to build your shader incrementally, out of several different pieces. Say one of your shader writers creates a cool per-pixel lighting solution, while another one figures out a neat procedural effect such as marble. With Cg, you can easily create each of these as functions, and combine them together however you think makes sense (perhaps, just multiplying the two values together). With the assembly interface, you would probably need to rewrite one of the shaders, since the two pieces of the shader need to agree on which registers get used to hold various pieces of data. You can't do this at all in a fixed-function pipeline, since there is currently not support for procedural surfaces, or for per-pixel lighting. Also, the standard library provides you with a ton of useful & tested functions that would take a lot work to replicate for each shader in assembly. For example, calculating the sin() of a value is just one function call in the standard library, but would easily consist of more than a dozen assembly instructions for GeForce 3 and GeForce 4.


Cg ํ”„๋กœ๊ทธ๋žจ์€ ์šฉ๋Ÿ‰์ด ์–ผ๋งˆ๋‚˜ ํฝ๋‹ˆ๊นŒ? ์–ด๋–ค ์ข…๋ฅ˜์˜ ๋ฐ์ดํƒ€ ์œ ํ˜•์ด ์ง€์›๋˜๋‚˜์š”? Cg ํ”„๋กœ๊ทธ๋žจ๊ฐ„์— ๋ฐ์ดํƒ€๋ฅผ ๊ณต์œ ํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๊นŒ? #

Cg ํ”„๋กœ๊ทธ๋žจ ๊ธธ์ด์˜ ํ•œ๊ณ„๋Š” ๋‹น์‹ ์ด ์ปดํŒŒ์ผํ•˜๊ณ  ์žˆ๋Š” ํƒ€๊ฒŸ์— ๋”ฐ๋ผ ์šด์šฉ๋ฉ๋‹ˆ๋‹ค. ์˜ˆ๋ฅผ ๋“ค๋ฉด, Directx 8 ์ •์  ์…ฐ์ด๋”๋Š” 128 ๊ฐœ์˜ ์–ด์…ˆ๋ธ”๋ฆฌ ๋ช…๋ น์œผ๋กœ ์ œํ•œ๋ฉ๋‹ˆ๋‹ค. ๊ทธ๋Ÿฌ๋ฏ€๋กœ ๋งŒ์•ฝ ๋‹น์‹ ์ด 128 ๋ณด๋‹ค ๋” ๋งŽ์€ ์ˆ˜์˜ ๋ช…๋ น์„ ์ปดํŒŒ์ผํ•˜๊ณ  ์žˆ๋Š” Cg ํ”„๋กœ๊ทธ๋žจ์„ ์ž‘์„ฑํ•œ๋‹ค๋ฉด, ๋‹น์‹ ์€ ๋‹น์‹ ์˜ ์ฝ”๋“œ๋ฅผ ์žฌ์ž‘์„ฑํ•  ํ•„์š”๊ฐ€ ์žˆ์Šต๋‹ˆ๋‹ค. NVIDIA's Cg Compiler doesn't do any magical multipass behind your back to break those strict limits, as our feedback from developers was clearly telling us they wanted to handle that part of the code. ๊ทธ๊ฒƒ์€ ์ฐจํ›„ ์‚ดํŽด๋ณผ ๊ฒƒ์ž…๋‹ˆ๋‹ค.

Cg ์ •์  ํ”„๋กœ๊ทธ๋žจ๊ณผ fragment ํ”„๋กœ๊ทธ๋žจ๊ณผ๋Š” ์–ผ๋งˆ๋‚˜ ์ฐจ์ด๊ฐ€ ์žˆ์Šต๋‹ˆ๊นŒ? #

Cg vertex programs and Cg fragment programs are specifically targeted at vertex shaders and pixel shaders, respectively. Given a particular target piece of hardware, the Cg program for vertex operations will be compiled at runtime into the API interface of choice (OpenGL or Direct3D) with the correct instruction set for the vertex processor for that hardware. Likewise, a Cg program for fragments (pixels) will be compiled at runtime for the pixel shader. The instruction sets for these processors differ, so the expression of the Cg program for vertex and pixel programs may differ accordingly. For each of these programs, the data results and inputs must match, so that the information produced per vertex is the correct information that is called for per pixel.

But from a syntax point of view, Cg programs for Vertex and Pixel are more or less the same, whether they're targeted at the vertex or fragment (pixel in Direct3D terminology) level. Texturing is not possible in a program targeted at the vertex level, and so texture functions, as well as functions to compute derivatives (often used in texturing) will not compile if targeted at a vertex profile. But one of the key ideas of Cg is that you can use the same language to represent programs that run on the vertex engine, fragment engine, or any other programmable engines that might be dreamed up for future architectures.

Cg ์…ฐ์ด๋”๋“ค์€ ์žฌ์‚ฌ์šฉ๊ฐ€๋Šฅํ•ฉ๋‹ˆ๊นŒ? ๋˜๋Š” ์ผ๋ฐ˜์ ์œผ๋กœ ํŠน์ • ๊ฒฝ์šฐ์—๋งŒ ์ด›์ ์ด ๋งž์ถฐ์ ธ ์žˆ์Šต๋‹ˆ๊นŒ? #

๋ฌผ๋ก , ์ด๊ฒƒ์€ Cg ํ”„๋กœ๊ทธ๋žจ์„ ์ž‘์„ฑํ•˜๋Š” ์‚ฌ๋žŒ์—๊ฒŒ ๋งŽ์€ ๋ถ€๋ถ„์ด ๋‹ฌ๋ ค์žˆ์Šต๋‹ˆ๋‹ค. ํ™•์‹คํžˆ ์‚ฌ๋žŒ๋“ค์ด Cg์ƒ์—์„œ ์žฌ์‚ฌ์šฉ๊ฐ€๋Šฅํ•œ ๋งŽ์€ ์œ ์šฉํ•œ ํ•จ์ˆ˜๋“ค์ด ์กด์žฌํ•ฉ๋‹ˆ๋‹ค. ์˜ˆ๋ฅผ ๋“ค๋ฉด, Cg ํ”„๋กœ๊ทธ๋žจ๋“ค๋‚ด์— ๋„˜๊ฒจ์ง€๋Š” ๋งค๊ฐœ๋ณ€์ˆ˜๋“ค์€ ์‹คํ–‰์‹œ ํ„ธ์˜ ์ƒ‰์ƒ๊ฐ™์€ ์š”์†Œ๋‚˜ ํ„ธ์ด ์–ผ๋งˆ๋‚˜ ๊ธธ์–ด์งˆ ๊ฒƒ์ธ๊ฐ€, ์–ผ๋งˆ๋‚˜ ๊ตต๊ฒŒ ํ•  ๊ฒƒ์ธ๊ฐ€๋“ฑ๋“ฑ์„ ๋ณ€๊ฒฝํ•˜๊ธฐ ์œ„ํ•ด ๋ฏธ์„ธํ•˜๊ฒŒ ์กฐ์ •๋  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค.

๊ทธ๋ž˜์„œ ๋ณด๋‹ค ๋„“์€ ๋А๋‚Œ์œผ๋กœ ๋ณธ๋‹ค๋ฉด, ์–ด์…ˆ๋ธ”๋ฆฌ์™€ ๋ฐ˜๋Œ€๋กœ ์žฌ์‚ฌ์šฉ์„ฑ๊ณผ ์ด์‹์„ฑ์€ Cg์„ ์‚ฌ์šฉํ•˜๋Š” ํ•ต์‹ฌ์ ์ธ ์žฅ์ ์ด๋ผ๊ณ  ๋ณผ ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค. ํ•˜๋‚˜์˜ ํ”„๋กœ์ ํŠธ๋ฅผ ์œ„ํ•ด ์ž‘์„ฑ๋œ ์ฝ”๋“œ๋Š” ํ”„๋กœ์ ํŠธ์— ๊ฑธ์ณ์„œ, ๊ทธ๋ฆฌ๊ณ  ๊ฐœ๋ฐœ์ž ์‚ฌ์ด์—์„œ ๊นŒ์ง€๋„ ๊ณต์œ ๋  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค. ๋‚˜๋Š” ์šฐ๋ฆฌ๊ฐ€ ์ปค๋ฎค๋‹ˆํ‹ฐ ์›น์‚ฌ์ดํŠธ์ƒ์—์„œ ๋Š˜์–ด๋‚˜๊ณ  ์žˆ๋Š” ์ €์žฅ๋œ ์…ฐ์ด๋” ์ฝ”๋“œ๋“ค์„ ๋ณผ ์ˆ˜ ์žˆ์„ ๊ฒƒ์„ ํ™•์‹ ํ•ฉ๋‹ˆ๋‹ค.

Cg ํ‘œ์ค€ ๋ผ์ด๋ธŒ๋Ÿฌ๋ฆฌ๋Š” ๋ฌด์—‡์ž…๋‹ˆ๊นŒ? #

The Cg Standard Library was designed to provide many of the often-used math functions from the standard C library, and also some shading-specific routines that are commonly used in shading languages. Routines ranging from sin(), exp(), and cross(), to refract(), distance(), and noise(), are all included in the Cg Standard Library.

Can you explain how Connectors and Data Domains work and why they're necessary? #

Cg is different from, say, C, in that it is designed to work on a stream of data. An example would be a stream of vertices that represent a 3D model. There are points in the pipeline where one stream of data is converted into a different stream of data, such as taking a stream of vertices, and rasterizing the triangles represented by those vertices. The data in are vertices, the data out are fragments (or pixels, in Direct3D terminology). Connectors are a way of representing this change in the data stream. A connector mostly looks like a C struct, but some of the fields in the connector change when moving between, say, the vertex and fragment sides of the connector.

What does the Cg Runtime Library provide, and in what cases would a developer want to use it? #

The Cg Runtime Library provides several useful functions. First, it allows a program to compile their Cg programs on-the-fly, very quickly. Cg programs can also be pre-compiled, and the output of those programs can be saved off in a game or other application. But the advantage of compiling on-the-fly is that the Cg program, which is not chip-specific, can be optimized by the compiler for each piece of hardware upon which the program is run. So, if someone writes a Cg program to, say, bumpmap a surface, the bumpmapping technique can be compiled down optimally for each different GPU on which the application runs. The other big function of the Cg Runtime Library is to let the application tweak parameters of the shader at runtime. If an app precompiles the bumpmap without using the Cg Runtime Library, and then at application runtime, the app decides that the bumpmaps need to change in depth, for example, the application would need to have pre-built a separate shader that knows how to draw deeper bumpmaps. By using the Cg Runtime, the application can instead just change a parameter passed in to the Cg program, re-compile on-the-fly, and render using that Cg program's output automatically.

OpenGL๊ณผ Direct3D ๊ฐ๊ฐ์˜ Cg ๋Ÿฐํƒ€์ž„ ๋ผ์ด๋ธŒ๋Ÿฌ๋ฆฌ๋Š” ์–ด๋–ค ์ฐจ์ด๊ฐ€ ์žˆ์Šต๋‹ˆ๊นŒ? ์–‘์ชฝ๋‹ค ๋‹ค๋ฅธ์ชฝ๋ณด๋‹ค ์ž‡์ ์ด ์žˆ๋Š” ๊ฒฝ์šฐ๊ฐ€ ์žˆ์„๊นŒ์š”? #

Because Direct3D and OpenGL differ in their APIs, the Cg Runtime interface is different for Direct3D versus OpenGL. The same functionality is available, but we have tried to make the Cg Runtime for Direct3D look consistent with the rest of Direct3D, while the Cg Runtime for OpenGL looks more familiar to OpenGL programmers.

ํ™•์‹คํžˆ, ์ด๊ฒƒ์€ ๋‹จ์ง€ ์‹œ์ž‘์ผ ๋ฟ์ž…๋‹ˆ๋‹ค. ๋‹ค์Œ ๋‹จ๊ณ„๋Š” ๋ญ์ฃ ? #

Cg์€ GPU์ƒ์—์„œ์˜ ๊ทธ๋ž˜ํ”ฝ์˜ ์ƒ์œ„ ๋ ˆ๋ฒจ ์–ธ์–ด ํ”„๋กœ๊ทธ๋ž˜๋ฐ์— ๋Œ€ํ•œ ๊ธฐ๋ณธํ‹€์ด๋ผ๊ณ  ํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค. ์ด๊ฒƒ์€ ๋‹จ์ง€ ์‹œ์ž‘์ผ ๋ฟ์ž…๋‹ˆ๋‹ค. ์™œ๋ƒํ•˜๋ฉด ์šฐ๋ฆฌ๋Š” ๋‹จ์ง€ programmableํ•œ GPU๋ฅผ ์ƒ์‚ฐํ•˜๋Š” ๊ฒƒ์„ ์‹œ์ž‘ํ–ˆ์„ ๋ฟ์ด๋‹ˆ๊นŒ์š”. ์ฐจ์„ธ๋Œ€ GPU๋Š” ๋” ์œ ์—ฐํ•˜๊ณ  ๋ณด๋‹ค๋” ํ”„๋กœ๊ทธ๋ž˜๋ฐ์ด ๊ฐ€๋Šฅํ•˜๊ฒŒ ๋  ๊ฒƒ์ด๋ฉฐ, ํ›จ์”ฌ ๋” ๊ฐ•๋ ฅํ•ด ์งˆ ๊ฒƒ์ž…๋‹ˆ๋‹ค. ๋งˆ๋ฒ•๊ณผ ๊ฐ™์€ ์‹ค์‹œ๊ฐ„ ์ปดํŒŒ์ผ์— ์˜ํ•ด์„œ, ์ด ์ƒˆ๋กœ์šด GPU๋“ค์€ ์—ฌ์ „ํžˆ Cg์„ ์‚ฌ์šฉํ•˜์—ฌ ํ”„๋กœ๊ทธ๋ž˜๋ฐ์ด ๊ฐ€๋Šฅํ•˜๊ฒŒ ๋  ๊ฒƒ์ž…๋‹ˆ๋‹ค. ๊ทธ๋ฆฌ๊ณ  ๋˜ํ•œ ์˜ค๋Š˜๋‚ ์˜ Cg ํ”„๋กœ๊ทธ๋žจ์€ ๋ฏธ๋ž˜์˜ GPU์—๋„ ์ˆ˜์ •์—†์ด ์‹คํ–‰๋  ์ˆ˜ ์žˆ์„ ๊ฒƒ์ž…๋‹ˆ๋‹ค. ์ด๊ฒƒ์ด ๋ฐ”๋กœ Cg์˜ ์•„๋ฆ„๋‹ค์›€์ด์ฃ  : Cg๋Š” Cg๊ฐ€ ๋™์ž‘ํ•˜๋Š”๋ฐ ์žˆ์–ด์„œ API ๋…๋ฆฝ์ ์ด๋ฉฐ, ํ”Œ๋ ›ํผ ๋…๋ฆฝ์ ์ด๊ณ  ์ƒˆ๋กœ์šด GPU์˜ ์ƒ์‚ฐ์— ๋Œ€ํ•ด์„œ๋„ ๋…๋ฆฝ์ ์ž…๋‹ˆ๋‹ค. ๊ทธ๋Ÿฌ๋ฏ€๋กœ, Cg ํ”„๋กœ๊ทธ๋ž˜๋ฐ์˜ ์•ž์—๋Š” ๊ธธ๊ณ  ํฅ๋ฏธ์ง„์ง„ํ•œ ๋ฏธ๋ž˜๊ฐ€ ํŽผ์ณ์ ธ ์žˆ๋‹ค๊ณ  ๋งํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค.

Valid XHTML 1.0! Valid CSS! powered by MoniWiki
last modified 2010-10-28 12:42:52
Processing time 0.4782 sec